{
  "openapi": "3.1.0",
  "info": {
    "title": "Apelora control plane API",
    "description": "Inventory, audit and identity for an Apelora fabric. Inventory responses name their source (mock or Incus) and when they were observed.\n\nConventions: a list answers `items`; a paged list also answers `next` while older entries remain, which the next request passes as `after`. Something created at once answers 201 with it, something queued answers 202 with how to follow it (a job or an operation), and a change or removal with nothing to return answers 204. A removal that needs a name typed again takes it as the `confirm` query parameter. A check that changes nothing has a noun path (`…/evacuation`, `…/migration`, `…/restoration`). `Idempotency-Key` makes a request that queues work safe to repeat; other requests ignore it. An error answers `error.code` and `error.message`; each code has one status.",
    "license": {
      "name": "AGPL-3.0-only",
      "identifier": "AGPL-3.0-only"
    },
    "version": "v1"
  },
  "paths": {
    "/api/v1/alerts": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Firing alerts (most severe and oldest first) with acknowledgement and silence, the silences\nin force, counts by severity and whether the evaluator runs. Needs `cluster.view`.",
        "operationId": "alerts",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/channels": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Webhook channels with their delivery state. The full URL only for callers who may configure\nchannels. Needs `cluster.view`.",
        "operationId": "alert_channels",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertChannelList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Adds a webhook channel. HTTPS only; the signing secret is named, never sent. Needs\n`alert.configure`; audited as `alert.channel.create` (host only, not the URL).",
        "operationId": "create_alert_channel",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertChannelRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertChannel"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `name_taken`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/channels/{id}": {
      "put": {
        "tags": [
          "alerts"
        ],
        "summary": "Changes a webhook channel. Needs `alert.configure`; audited as `alert.channel.update`.",
        "operationId": "update_alert_channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Channel id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertChannelRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertChannel"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `name_taken`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "alerts"
        ],
        "summary": "Deletes a webhook channel; messages still waiting for it are dropped by the relay. Needs\n`alert.configure`; audited as `alert.channel.delete`.",
        "operationId": "delete_alert_channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Channel id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/channels/{id}/test": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Queues a test notification for one channel through the same outbox path as real alerts; the\nchannel's delivery state shows the outcome within seconds. Needs `alert.configure`; audited as\n`alert.channel.test` in the same transaction as the message.",
        "operationId": "test_alert_channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Channel id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertChannelTest"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `channel_disabled`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/history": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Resolved alerts, newest first, paged with `after` and `next`. Kept 90 days. Needs `cluster.view`.",
        "operationId": "alert_history",
        "parameters": [
          {
            "name": "after",
            "in": "query",
            "description": "Paging: the `next` of the previous page.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "1 to 200 (default 50).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertHistory"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/rules": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "The built-in rules with their parameters in force, their defaults and what the evaluator's\nlast pass said about each source. Needs `cluster.view`.",
        "operationId": "alert_rules",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/rules/{rule}": {
      "put": {
        "tags": [
          "alerts"
        ],
        "summary": "Changes a rule's parameters (on or off, threshold within the rule's bounds, duration up to a\nday, severity). Takes effect on the evaluator's next pass. Needs `alert.configure`; audited\nas `alert.rule.update` with the parameters before and after.",
        "operationId": "update_alert_rule",
        "parameters": [
          {
            "name": "rule",
            "in": "path",
            "description": "Rule id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertRuleParams"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleItem"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/silences": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Silences a rule (every subject, or one) for `minutes` from now: no notification is sent for\nits alerts that fire or resolve meanwhile. Evaluation and history go on. Needs\n`alert.respond`; audited as `alert.silence.create`.",
        "operationId": "create_alert_silence",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertSilenceRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertSilence"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/silences/{id}": {
      "delete": {
        "tags": [
          "alerts"
        ],
        "summary": "Ends a silence now. Needs `alert.respond`; audited as `alert.silence.end`. 404 when it is\nnot in force (ended or run out).",
        "operationId": "end_alert_silence",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Silence id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/{id}/acknowledge": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Acknowledges a firing alert: who, when and an optional note. It keeps firing until its\ncondition clears; acknowledging tells others someone is on it. Refused (409) when it is not\nfiring (`not_firing`) or was acknowledged already (`already_acknowledged`). Needs\n`alert.respond`; audited as `alert.acknowledge`.",
        "operationId": "acknowledge_alert",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Alert id",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertAcknowledgeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertItem"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `already_acknowledged`, `not_firing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "Applications the caller may see, each with design status, derived runtime status, replica\nhealth, and the actions they may take now. Needs `application.view`.",
        "operationId": "applications",
        "parameters": [
          {
            "name": "includeArchived",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "Creates an application in an environment, optionally with its first draft. Needs\n`application.create` on the environment's project.",
        "operationId": "create_application",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApplication"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationInfo"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `draft_conflict`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "One application with its modules (desired and observed), versions and recent operations.\nNeeds `application.view`.",
        "operationId": "application",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationDetail"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "applications"
        ],
        "summary": "Changes an application's description or icon (its name cannot change). Needs `application.design`.",
        "operationId": "update_application",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateApplication"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationInfo"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/access": {
      "get": {
        "tags": [
          "sessions"
        ],
        "summary": "What the caller may open on each instance of the application now, with the reason when not.\nThis is the source for the interface's menu entries. Needs `application.view`.",
        "operationId": "application_access",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/archive": {
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "Archives an application that is not running; it leaves the default list and keeps its data.\nNeeds `application.delete`.",
        "operationId": "archive_application",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `still_running`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/deployments": {
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "Deploys the design: saves it as a new revision and queues the planned changes. Refuses\nthe whole deployment if any module conflicts with an existing instance. Needs `deploy`.",
        "operationId": "deploy_application",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Makes the request safe to repeat",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeployRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeployResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `confirmation_required`, `incus_project_exists`, `not_published`, `operation_in_progress`, `plan_conflict`, `project_mismatch`, `quota_exceeded`, `service_range_exhausted`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`, `incus_project_not_ready`, `quota_unverifiable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/draft": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "The application's working document. 404 when it has none yet. Needs `application.view`.",
        "operationId": "application_draft",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DraftDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `no_draft`, `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "applications"
        ],
        "summary": "Saves the draft as the next version. Refused with 409 `draft_conflict` (and the current\nversion) when someone saved since `baseVersion`; nothing is overwritten. Needs `application.design`.",
        "operationId": "save_application_draft",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveDraft"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DraftDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/events": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "What happened to the application: creation, saves, versions, deployments, operations,\nrefusals. Needs `application.view`.",
        "operationId": "application_events",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/instances/{instance}/sessions": {
      "post": {
        "tags": [
          "sessions"
        ],
        "summary": "Opens a session: checks the caller, the instance and the approval rule, and answers with a\nsingle-use ticket for the websocket. Needs `instance.console` (terminal, PowerShell) or\n`instance.desktop` (RDP) on the application; in production also an approval\n(`Apelora-Approval: <id>`) of `instance.console` on `instance:<application>/<instance>`.",
        "operationId": "open_remote_session",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "instance",
            "in": "path",
            "description": "Instance name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewSession"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionTicket"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `instance_state_unknown`, `session_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `console_disabled`, `database_not_configured`, `no_randomness`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/migration": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "Dry run of migrating the application to another server: for each instance whether it keeps\nrunning, what is copied and what blocks it. Changes nothing. Needs `application.operate`.",
        "operationId": "preview_application_migration",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "target",
            "in": "query",
            "description": "The server to move the application to.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MigrationPreview"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `not_deployed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/operations": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "Recent operations of the application, newest first. Needs `application.view`.",
        "operationId": "application_operations",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperationList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "Starts, shuts down (graceful), stops (immediate), restarts or migrates the application's\ninstances, in dependency order where that matters, as an asynchronous operation. Succeeds\nonly when Incus confirms each instance's state (and, for a migration, its new server). Needs\n`application.operate` on the application. It only touches instances this application owns;\nnetworks, volumes, data and other applications are left alone.",
        "operationId": "operate_application",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Makes the request safe to repeat",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OperateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperationAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `action_not_available`, `already_running`, `already_stopped`, `confirmation_required`, `member_unreachable`, `migration_blocked`, `not_deployed`, `nothing_deployed`, `nothing_to_do`, `operation_in_progress`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer. `error.code`: `incus_unreachable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/operations/{id}": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "One operation with the progress of each phase and instance. Needs `application.view`.",
        "operationId": "application_operation",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Operation id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperationDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/plan": {
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "What deploying the design would change, without changing anything. Needs `deploy`.",
        "operationId": "plan_application",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlanRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Plan"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `project_mismatch`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `quota_unverifiable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/restore": {
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "Brings an archived application back. Needs `application.delete`.",
        "operationId": "restore_application",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `still_running`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/status": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "The application's instances as Incus reports them, by module. Needs `read-inventory`.",
        "operationId": "application_status",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project",
            "in": "query",
            "description": "Only this Incus project.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationStatus"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/versions": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "Versions of the application, newest first. Needs `application.view`.",
        "operationId": "application_versions",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "Releases the current draft as the next immutable published version. Refused while the draft\nis invalid or when this draft version is already published. Needs `application.design`.",
        "operationId": "publish_application",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublishRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionInfo"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `no_draft`, `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `already_published`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "422": {
            "description": "The request is well formed but cannot be carried out; the error says why. `error.code`: `draft_invalid`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/versions/{revision}": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "The document of one version. Needs `application.view`.",
        "operationId": "application_version",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision",
            "in": "path",
            "description": "Version number",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionDocument"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/volumes": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "The application's volumes, with what Incus says about each now. Needs `application.view`.",
        "operationId": "application_volumes",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationVolumes"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/volumes/{volume}": {
      "delete": {
        "tags": [
          "applications"
        ],
        "summary": "Deletes one of the application's volumes and its snapshots, for good. The volume's Incus\nname must be typed again; refused while an instance uses it. Needs `application.delete`\n(and an approval where the policy asks for one); audited.",
        "operationId": "delete_application_volume",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "confirm",
            "in": "query",
            "description": "The volume's Incus name again, typed by the person deleting it.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `volume_in_use`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "applications"
        ],
        "summary": "Grows one of the application's volumes, also while its instance runs. Volumes only grow:\na smaller size is refused. Needs `application.deploy`; audited.",
        "operationId": "grow_application_volume",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GrowVolume"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/volumes/{volume}/backups": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "The volume's backups, oldest first, whether each still exists, and its schedules. Needs\n`application.view`.",
        "operationId": "volume_backups",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VolumeBackupList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "Backs the volume up now: a copy, through a short-lived snapshot, into the backup pool on\nanother member. Kept until someone deletes it (`delete_backup`); scheduled backups are\npruned to what the schedule keeps. Queues a `volume.backup` job. Needs `application.operate`;\naudited.",
        "operationId": "back_up_volume",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Makes the request safe to repeat",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `backup_pool_missing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/volumes/{volume}/backups/{backup}": {
      "delete": {
        "tags": [
          "applications"
        ],
        "summary": "Deletes one backup copy. The volume it was taken from is left as it is. The backup's\nIncus name must be typed again. A copy Incus no longer has is forgotten anyway, so a\nrecord of a missing copy can be cleared. Needs `application.delete` (and an approval\nwhere a policy asks for one); audited.",
        "operationId": "delete_volume_backup",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "backup",
            "in": "path",
            "description": "The backup's Incus name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "confirm",
            "in": "query",
            "description": "The backup's Incus name again, typed by the person deleting it.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/volumes/{volume}/backups/{backup}/restoration": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "Dry run of restoring the volume from one of its backups: what is replaced (data written\nsince the backup, the volume's snapshots), which instances must be stopped, where the safety\nbackup goes, and the steps. Changes nothing. Needs `application.operate`.",
        "operationId": "preview_volume_restore",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "backup",
            "in": "path",
            "description": "The backup's Incus name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "safetyBackup",
            "in": "query",
            "description": "Take a safety backup of the current data first (default true).",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestorePreview"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/volumes/{volume}/backups/{backup}/restore": {
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "Restores the volume from one of its backups, after the dry run passes again and the\nvolume's name is typed: a safety backup of the current data first (unless declined), then\nthe backup is copied over the volume. Every instance using it must be stopped; they stay\nstopped. Queues a `volume.restore` job. Needs `application.operate` (and an approval where\na policy asks); audited with the job.",
        "operationId": "restore_volume_backup",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "backup",
            "in": "path",
            "description": "The backup's Incus name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Makes the request safe to repeat",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreVolumeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `restore_blocked`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/volumes/{volume}/schedules": {
      "put": {
        "tags": [
          "applications"
        ],
        "summary": "Sets or turns off the volume's snapshot and backup schedules. A new or changed schedule\nfirst runs at the worker's next pass (within a minute). Needs `application.deploy`; audited.",
        "operationId": "set_volume_schedules",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetVolumeSchedules"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `backup_pool_missing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/volumes/{volume}/snapshots": {
      "get": {
        "tags": [
          "applications"
        ],
        "summary": "The volume's snapshots, oldest first. Needs `application.view`.",
        "operationId": "volume_snapshots",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "Takes a snapshot of the volume, named after the time (`snap-YYYYMMDD-HHMMSS`). While an\ninstance runs the snapshot is only crash-consistent; the response says which. Snapshots\nare not backups: they live in the same pool. Needs `application.operate`; audited.",
        "operationId": "take_volume_snapshot",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotTaken"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `snapshots_not_allowed`, `volume_missing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/volumes/{volume}/snapshots/{snapshot}": {
      "delete": {
        "tags": [
          "applications"
        ],
        "summary": "Deletes one snapshot of the volume. Needs `application.delete`; audited.",
        "operationId": "delete_volume_snapshot",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "snapshot",
            "in": "path",
            "description": "Snapshot name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{name}/volumes/{volume}/snapshots/{snapshot}/restore": {
      "post": {
        "tags": [
          "applications"
        ],
        "summary": "Puts the volume back to a snapshot: everything written since is lost. The snapshot's name\nmust be typed again, and every instance using the volume must be stopped. Needs\n`application.operate` (and an approval where the policy asks for one); audited.",
        "operationId": "restore_volume_snapshot",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Application name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volume",
            "in": "path",
            "description": "The volume's Incus name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "snapshot",
            "in": "path",
            "description": "Snapshot name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmSnapshot"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `volume_in_use`, `volume_missing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/approvals": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Requests and approvals: your own, plus every open one if you may approve. Needs `approval.request` or `approval.grant`.",
        "operationId": "approvals",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApprovalList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Asks for approval of one risky action on one target. You must be allowed to do the action\nyourself; someone else with `approval.grant` then decides. Needs `approval.request`.",
        "operationId": "request_approval",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewApproval"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApprovalDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/approvals/{id}/approve": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Approves a request made by someone else. Needs `approval.grant`, held by a signed-in person: API\ntokens are refused (`approval_needs_a_person`). The approval is good for 30 minutes, once.",
        "operationId": "approve_approval",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Approval id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApprovalDto"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `approval_needs_a_person`, `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "410": {
            "description": "No longer possible: it expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/approvals/{id}/cancel": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Withdraws your own pending request. Needs `approval.request`.",
        "operationId": "cancel_approval",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Approval id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApprovalDto"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/approvals/{id}/reject": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Rejects a request. Needs `approval.grant`, held by a signed-in person (API tokens are refused).",
        "operationId": "reject_approval",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Approval id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApprovalDto"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `approval_needs_a_person`, `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit": {
      "get": {
        "tags": [
          "audit"
        ],
        "summary": "Audit events the caller may read, newest first, filtered by actor, target, action prefix,\noutcome and time, and paged with `after` and `next`. Needs `audit.read` (platform-wide, or limited to\nthe events of the caller's organisations, projects and applications) and a database.",
        "operationId": "audit",
        "parameters": [
          {
            "name": "actor",
            "in": "query",
            "description": "Who acted: their stable id (`user:<uuid>`, `service:<uuid>`, `token:<name>`) or, ignoring\ncase, the name they had when they acted.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "target",
            "in": "query",
            "description": "What was acted on, exactly as recorded (e.g. `local-account:ada` or a group's name).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "query",
            "description": "Only actions starting with this, e.g. `role.` or `emergency_access.`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "outcome",
            "in": "query",
            "description": "`success`, `denied` or `failed`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "RFC 3339: events at or after this time.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "RFC 3339: events before this time.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "after",
            "in": "query",
            "description": "Paging: the `next` of the previous page.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Events per page, 1 to 500 (default 100). Not used by the export.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit/export": {
      "get": {
        "tags": [
          "audit"
        ],
        "summary": "Exports the audit events the caller may read, with the same filters as the list (`limit`\ndoes not apply), newest first, as CSV or JSON lines. Streamed one database page at a time.\nNeeds `audit.read`; the export itself is audited as `audit.exported` with its filters.",
        "operationId": "audit_export",
        "parameters": [
          {
            "name": "actor",
            "in": "query",
            "description": "Who acted: their stable id (`user:<uuid>`, `service:<uuid>`, `token:<name>`) or, ignoring\ncase, the name they had when they acted.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "target",
            "in": "query",
            "description": "What was acted on, exactly as recorded (e.g. `local-account:ada` or a group's name).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "query",
            "description": "Only actions starting with this, e.g. `role.` or `emergency_access.`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "outcome",
            "in": "query",
            "description": "`success`, `denied` or `failed`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "RFC 3339: events at or after this time.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "RFC 3339: events before this time.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "after",
            "in": "query",
            "description": "Paging: the `next` of the previous page.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Events per page, 1 to 500 (default 100). Not used by the export.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "format",
            "in": "query",
            "description": "`csv` or `jsonl` (one JSON object per line, as the list returns them). Default `jsonl`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The events: CSV with a header row, or one JSON object per line",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              },
              "application/x-ndjson": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/capacity": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "How much CPU, memory and volume space the cluster has free, per server and in total, for\ncomparing with a design. Read-only. With `cluster.view` servers are named; with\n`capacity.view` (held by designers and operators at any scope) they are numbered.",
        "operationId": "capacity",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CapacityReport"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "The Incus server and its cluster members. Needs `read-inventory`.",
        "operationId": "cluster",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClusterResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/groups": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "Cluster groups and their members (empty on a standalone server). Read-only; needs\n`cluster.view`.",
        "operationId": "cluster_groups",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClusterGroupList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/join-tokens": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "Join tokens waiting to be used (no secrets). Needs `manage-infrastructure`.",
        "operationId": "join_tokens",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JoinTokenList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Approves a new cluster member: asks Incus for a single-use join token. Needs\n`manage-infrastructure`. The token is in this response only.",
        "operationId": "create_join_token",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateJoinToken"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JoinTokenCreated"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/join-tokens/{member}": {
      "delete": {
        "tags": [
          "cluster"
        ],
        "summary": "Withdraws a new member's approval: revokes its unused join token. Needs\n`manage-infrastructure`.",
        "operationId": "revoke_join_token",
        "parameters": [
          {
            "name": "member",
            "in": "path",
            "description": "Name the token was issued for",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/members": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "Members with their database role (voter, stand-by, spare), the leader, other roles,\nfailure domain, groups and Incus release; the database majority (how many voters answer,\nhow many are needed, how many more can be lost); and version skew against the pinned\nIncus release with what blocks an upgrade. Read-only; needs `cluster.view`.",
        "operationId": "cluster_members",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClusterMembersReport"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "500": {
            "description": "Apelora failed; the response's `x-request-id` finds it in the server log. `error.code`: `invalid_place`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/members/{member}/evacuate": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Evacuates a cluster member through Incus after re-running the dry run: refused while\nanything blocks it. Needs `manage-infrastructure` and the admin identity; audited.",
        "operationId": "evacuate_member",
        "parameters": [
          {
            "name": "member",
            "in": "path",
            "description": "Cluster member name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmMember"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberStateStarted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `evacuation_blocked`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/members/{member}/evacuation": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "Dry run of evacuating a cluster member: per instance, what Incus will do and what it means\nfor the application; what blocks it; what to accept. Changes nothing.",
        "operationId": "preview_evacuation",
        "parameters": [
          {
            "name": "member",
            "in": "path",
            "description": "Cluster member name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvacuationPreview"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/members/{member}/fencing": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Confirms that a failed server is powered off (or cut off from the shared storage). This\nfences it: Apelora then restarts its modules on shared storage on other servers. Refused\nunless Incus reports the member Offline. Needs `cluster.fence_confirm` and another person's\napproval; the member's name typed again; audited.",
        "operationId": "confirm_fenced",
        "parameters": [
          {
            "name": "member",
            "in": "path",
            "description": "Cluster member name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FenceConfirmation"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecoveryMember"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `member_not_offline`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/members/{member}/removal": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "Dry run of removing a cluster member for good: what is still on it, what blocks it and what\nto accept. Changes nothing.",
        "operationId": "preview_member_removal",
        "parameters": [
          {
            "name": "member",
            "in": "path",
            "description": "Cluster member name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RemovalPreview"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/members/{member}/remove": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Removes an evacuated, empty member from the cluster for good, after the check runs again:\nrefused while anything blocks it. Needs `cluster.manage`, the admin identity and the\nmember's name typed again; audited.",
        "operationId": "remove_member",
        "parameters": [
          {
            "name": "member",
            "in": "path",
            "description": "Cluster member name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmMember"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `removal_blocked`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/members/{member}/restore": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Restores an evacuated member: Incus moves its instances back and starts them. Needs\n`manage-infrastructure` and the admin identity; audited.",
        "operationId": "restore_member",
        "parameters": [
          {
            "name": "member",
            "in": "path",
            "description": "Cluster member name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmMember"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberStateStarted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/recovery": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "Failed members: whether each is fenced (and the evidence), or why Apelora waits; and per\ninstance whether it restarts on another server (and where) or waits (and why). Read-only;\nneeds `cluster.view`.",
        "operationId": "cluster_recovery",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecoveryReport"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/settings": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "Cluster-wide settings (offline and healing thresholds, database voters and stand-bys,\njoin-token lifetime, image replication and updates): the value set, Incus's default and\nwhether the default applies. Read with the admin identity, since Incus shows its\nconfiguration only to an unrestricted one (503 `cluster_admin_not_configured` without it);\nonly these keys are returned. Read-only; needs `cluster.view`.",
        "operationId": "cluster_settings",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClusterSettingsReport"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "cluster"
        ],
        "summary": "Changes cluster settings through Incus with the admin identity. Every key must be one the\nServers page lists and every value is checked. Settings that already hold the value are left\nout; nothing to change is refused. With `dryRun` it only reports (what each becomes and what\nto watch for). Applying needs `cluster.sensitive_change` and another person's approval of\n`cluster-settings:<keys joined by />` (`Apelora-Approval`), spent before the change, and is\naudited with the old and new values.",
        "operationId": "change_cluster_settings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangeSettings"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettingsChangeReport"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`, `invalid_setting`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `nothing_to_change`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cluster/upgrade": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "One step of the rolling upgrade. Apelora evacuates and restores. It does not install Incus:\n`upgraded` records that the package was upgraded on the server. Needs `cluster.evacuate`.",
        "operationId": "upgrade_cluster",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpgradeCommand"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpgradeView"
                }
              }
            }
          },
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpgradeView"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `evacuation_blocked`, `no_upgrade`, `not_upgraded`, `upgrade_blocked`, `upgrade_in_progress`, `upgrade_step`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/database-backups": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Whether Apelora's database is being backed up and a restore has been proven, from the records\nthe scripts leave in `APELORA_DB_BACKUP_DIR`. Needs `cluster.view`.",
        "operationId": "database_backups",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatabaseBackupReport"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Public. Reports that the service answers, the inventory provider, the authentication mode\nand whether Incus is reachable. Incus is asked at most every 15 s whatever the request rate;\nversions and error text are only on `GET /api/v1/system` (signed in).",
        "operationId": "health",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/api/v1/health/components": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "The state of each part of this installation: control plane, database, deployment workers,\njob queue, Incus, networks, storage pools and identity providers. Read-only; needs\n`cluster.view`.",
        "operationId": "health_components",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthReport"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/servers": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Each server's status, CPU, memory, storage and the instances on it, with warnings. Read-only;\nneeds `cluster.view`.",
        "operationId": "health_servers",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthServers"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/assignments": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Role assignments in the caller's scopes. Needs `user.view`.",
        "operationId": "assignments",
        "parameters": [
          {
            "name": "principalType",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "principalId",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "includeRevoked",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssignmentList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Grants a role to a person, group or automation identity at a scope. Needs `role.assign` there\nand every permission the role holds (no escalation); audited.",
        "operationId": "create_assignment",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewAssignment"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssignmentDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `assignment_refused`, `forbidden`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `user_disabled`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/assignments/preview": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Shows what an assignment would give before it is saved: what the person can already do at the\nscope, what they could do afterwards, which permissions would be inert, and whether you may\nsave it. Changes nothing. Needs `role.assign`.",
        "operationId": "preview_assignment",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewAssignment"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssignmentPreview"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/assignments/{assignment}": {
      "delete": {
        "tags": [
          "identity"
        ],
        "summary": "Revokes an assignment; the person loses it on their next request. Needs `role.assign` in its\nscope and every permission the role confers there (you can only take away what you could\ngrant). Refused when it would leave no enabled platform super admin.",
        "operationId": "revoke_assignment",
        "parameters": [
          {
            "name": "assignment",
            "in": "path",
            "description": "Assignment id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `revocation_refused`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `last_super_admin`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/audit": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Audit history the caller may read: the same filters and paging as `GET /api/v1/audit`.\nNeeds `audit.read`.",
        "operationId": "identity_audit",
        "parameters": [
          {
            "name": "actor",
            "in": "query",
            "description": "Who acted: their stable id (`user:<uuid>`, `service:<uuid>`, `token:<name>`) or, ignoring\ncase, the name they had when they acted.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "target",
            "in": "query",
            "description": "What was acted on, exactly as recorded (e.g. `local-account:ada` or a group's name).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "query",
            "description": "Only actions starting with this, e.g. `role.` or `emergency_access.`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "outcome",
            "in": "query",
            "description": "`success`, `denied` or `failed`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "RFC 3339: events at or after this time.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "RFC 3339: events before this time.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "after",
            "in": "query",
            "description": "Paging: the `next` of the previous page.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Events per page, 1 to 500 (default 100). Not used by the export.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/emergency-access": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Grants a person a platform role for a short time, with a recorded reason (break-glass). You\ncannot grant it to yourself; every request made with it is audited. Needs `platform.emergency_access`.",
        "operationId": "grant_emergency_access",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmergencyAccess"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssignmentDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `assignment_refused`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `self_grant`, `user_disabled`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/environments/{id}/incus-project": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Creates or adopts the environment's Incus project now (idempotent): the restricted project\nwith its default profile, granted to the deploy identity, then the quotas mirrored. An existing\nproject is adopted only when it carries this environment's marker or a platform administrator\nnamed it when creating the environment; otherwise 409 `incus_project_exists`. Needs\n`environment.manage` on the environment's project; 503 without an admin identity.",
        "operationId": "prepare_incus_project",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Environment id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IncusProjectPrepared"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `incus_project_exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/groups": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Groups the caller may see. Needs `user.view`.",
        "operationId": "groups",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Creates a group: an organisation's (needs `group.manage` there) or a platform group (platform\n`group.manage`). Mapping a group to a group of an identity provider or directory is\nplatform-only and needs the source (`externalSource`): only that source's credentials map\nonto it, and a directory group is named by its full DN.",
        "operationId": "create_group",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewGroup"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/groups/{group}/external": {
      "put": {
        "tags": [
          "identity"
        ],
        "summary": "Maps a platform group onto a group of an identity provider or directory, or sets the source of a\nmapping made before sources were recorded (`needsSource`). Needs platform `group.manage`, and,\nsince the source's members then receive the group's roles, the right to grant each of them\n(the escalation guard; `membership_refused`). A directory group is named by its full DN.",
        "operationId": "set_group_external",
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "description": "Group id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GroupExternal"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `membership_refused`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/groups/{group}/members": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Members of a group. Needs `user.view` or `group.manage` on the group's organisation.",
        "operationId": "group_members",
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "description": "Group id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/groups/{group}/members/{user}": {
      "put": {
        "tags": [
          "identity"
        ],
        "summary": "Adds a person to a group. Needs `group.manage`, and, since a member receives the group's roles,\nthe right to grant each of them to that person (the same escalation guard as a direct\nassignment; refused with `membership_refused`).",
        "operationId": "add_group_member",
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "description": "Group id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "user",
            "in": "path",
            "description": "User id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `membership_refused`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `last_super_admin`, `managed_by_provider`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "identity"
        ],
        "summary": "Removes a person from a group; their access through it ends on their next request. Needs `group.manage`.",
        "operationId": "remove_group_member",
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "description": "Group id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "user",
            "in": "path",
            "description": "User id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `membership_refused`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `last_super_admin`, `managed_by_provider`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/local-accounts": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Creates a local account and returns its one-time setup link, valid for 24 hours. The\nperson chooses their password with it; nobody else ever knows it. Needs `user.manage`.",
        "operationId": "create_local_account",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LocalAccountInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocalAccountCreated"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `username_taken`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/local-accounts/{id}/reset": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Takes a local account's password away, revokes every session of theirs and returns a new\none-time setup link (24 hours). Not for your own account (use Change password). Needs\n`user.manage`.",
        "operationId": "reset_local_account",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "User id of the local account",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocalAccountSetupLink"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `self_reset`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/organizations": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Organisations the caller may see. Needs `organization.view` (or a grant below that reaches them).",
        "operationId": "organizations",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Creates an organisation. Needs `organization.create` (platform).",
        "operationId": "create_organization",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewOrganization"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/organizations/{org}/projects": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Creates a project in an organisation. Needs `project.create` on the organisation.",
        "operationId": "create_project",
        "parameters": [
          {
            "name": "org",
            "in": "path",
            "description": "Organisation id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewProject"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/permissions": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Every permission, its class and the narrowest scope at which a grant takes effect.",
        "operationId": "permissions",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermissionList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/personal-tokens": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Everyone's personal tokens (or one person's), live ones and those that ended in the last 30\ndays. Needs `token.manage` on the platform.",
        "operationId": "personal_tokens",
        "parameters": [
          {
            "name": "user",
            "in": "query",
            "description": "Only this person's.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalTokenList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/personal-tokens/{id}": {
      "delete": {
        "tags": [
          "identity"
        ],
        "summary": "Revokes anyone's live personal token. Needs `token.manage` on the platform.",
        "operationId": "revoke_personal_token",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Token id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/policies": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Access policies (MFA and approval rules). Needs `access_policy.manage` or `audit.read`.",
        "operationId": "policies",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "identity"
        ],
        "summary": "Creates or updates a policy by name. `mfa`: `{\"environments\": [\"production\"], \"infrastructure\": true}`.\n`approval`: `{\"actions\": [\"cluster.evacuate\"]}` (extra actions that need approval where the API\nalready asks for it). Needs `access_policy.manage`.",
        "operationId": "save_policy",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SavePolicy"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/policies/{id}": {
      "delete": {
        "tags": [
          "identity"
        ],
        "summary": "Deletes a policy. Needs `access_policy.manage`.",
        "operationId": "delete_policy",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Policy id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/projects": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Projects the caller may see, optionally of one organisation. Needs `project.view`.",
        "operationId": "projects",
        "parameters": [
          {
            "name": "organization",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityProjectList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/projects/{projectId}/environments": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Environments of a project. Needs `project.view` on it.",
        "operationId": "environments",
        "parameters": [
          {
            "name": "projectId",
            "in": "path",
            "description": "Apelora project id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnvironmentList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Creates an environment. The Incus project it maps to is derived from the names (tenants cannot\nchoose it); platform administrators (`cluster.manage`) may map an existing one. When the\nderived project already exists and Apelora did not create it for this environment, nothing\nis created: 409 `incus_project_exists`. Needs `environment.manage`.",
        "operationId": "create_environment",
        "parameters": [
          {
            "name": "projectId",
            "in": "path",
            "description": "Apelora project id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewEnvironment"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnvironmentDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `incus_project_exists`, `reserved_name`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/quotas/{scope}/{id}": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "A scope's quota and use. Needs `organization.view` (organisation) or `project.view` (project,\nenvironment) on it, or `quota.manage`.",
        "operationId": "quota",
        "parameters": [
          {
            "name": "scope",
            "in": "path",
            "description": "organization, project or environment",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Its id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuotaView"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "identity"
        ],
        "summary": "Sets a scope's quota (all limits empty removes it), then mirrors the tightest applicable quota\nonto every environment beneath it. Needs `quota.manage`; or, below the organisation,\n`organization.update` on the organisation (projects, environments) or `project.update` on the\nproject (environments), and then never more than a quota above allows.",
        "operationId": "set_quota",
        "parameters": [
          {
            "name": "scope",
            "in": "path",
            "description": "organization, project or environment",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Its id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuotaLimits"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuotaChange"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`, `quota_above_parent`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/roles": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "The predefined and custom roles with their permissions.",
        "operationId": "roles",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Defines a custom role from explicit permissions. Needs `role.manage` (platform), and you may\nonly include permissions you hold yourself.",
        "operationId": "create_role",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewRole"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `would_escalate`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/roles/{role}": {
      "delete": {
        "tags": [
          "identity"
        ],
        "summary": "Deletes a custom role that no assignment uses. Needs `role.manage`.",
        "operationId": "delete_role",
        "parameters": [
          {
            "name": "role",
            "in": "path",
            "description": "Custom role id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/service-identities": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Registered service identities (the credentials Apelora uses for Incus and MAAS, and automation\nidentities that call this API). Needs `service_identity.manage`.",
        "operationId": "service_identities",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceIdentityList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Registers a service identity. Outbound kinds (workload, network, storage, provisioning) record\nonly the name of a credential held in the secret store; automation identities get an API token,\nshown once. Needs `service_identity.manage`.",
        "operationId": "create_service_identity",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewServiceIdentity"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceIdentityCreated"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/service-identities/{id}/disable": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Disables a service identity at once. Needs `service_identity.manage`.",
        "operationId": "disable_service_identity",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Service identity id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/service-identities/{id}/enable": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Re-enables a service identity. Needs `service_identity.manage`.",
        "operationId": "enable_service_identity",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Service identity id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-in": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Sign-in settings: identity providers (saved and from the environment), whether API tokens\nare accepted, and local accounts. Needs `platform.security.manage`.",
        "operationId": "sign_in_settings",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignInSettings"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-in/api-tokens": {
      "put": {
        "tags": [
          "identity"
        ],
        "summary": "Turns API tokens on or off. Turning them off is refused while no other way in remains (an\nidentity provider that answers, or local accounts that are on with at least one account set\nup), and for someone signed in with an API token (they would lock themselves out). Needs\n`platform.security.manage`; audited.",
        "operationId": "set_api_tokens",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiTokensRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiTokenSetting"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `locked_by_environment`, `would_lock_out`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-in/check": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Reads a provider's discovery document and key set, without saving anything: what an\nadministrator checks before saving. Needs `platform.security.manage`.",
        "operationId": "check_identity_provider",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderCheck"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer. `error.code`: `provider_unreachable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-in/directories": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "The directories people sign in with, each checked with a TLS connection now. Needs\n`platform.security.manage`.",
        "operationId": "directories",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectoryList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Adds a directory; it is offered on the sign-in page at once when enabled. Needs\n`platform.security.manage` (and an approval where the policy asks for one); audited.",
        "operationId": "create_directory",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DirectoryInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectoryView"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `conflict`, `directory_exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-in/directories/check": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Connects with TLS, binds as a test person and reads their entry and groups, without saving\nanything. Reports what it found or the precise reason it failed. Needs\n`platform.security.manage`.",
        "operationId": "check_directory",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DirectoryCheckRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectoryCheck"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-in/directories/{id}": {
      "put": {
        "tags": [
          "identity"
        ],
        "summary": "Changes a directory (including turning it off). Needs `platform.security.manage`; audited.",
        "operationId": "update_directory",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Directory id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DirectoryInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectoryView"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `conflict`, `directory_exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "identity"
        ],
        "summary": "Removes a directory: its people can no longer sign in with it; their accounts and roles in\nApelora stay. Its name must be typed again. Needs `platform.security.manage`; audited.",
        "operationId": "delete_directory",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Directory id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "confirm",
            "in": "query",
            "description": "The directory's name again.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-in/local-accounts": {
      "put": {
        "tags": [
          "identity"
        ],
        "summary": "Turns sign-in with local accounts on or off. Turning it off is refused while nothing else\nwould let people sign in, and for someone signed in with a local account. Turning it off\nalso ends every password session. Needs `platform.security.manage`; audited.",
        "operationId": "set_local_accounts",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LocalAccountsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocalAccountSetting"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `would_lock_out`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-in/providers": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Adds an identity provider; it is checked and applied at once. Needs\n`platform.security.manage` (and an approval where the policy asks for one); audited.",
        "operationId": "create_identity_provider",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProviderInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderView"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `conflict`, `provider_exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-in/providers/{id}": {
      "put": {
        "tags": [
          "identity"
        ],
        "summary": "Changes a provider saved in the Console. Needs `platform.security.manage`; audited.",
        "operationId": "update_identity_provider",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Provider id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProviderInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderView"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `conflict`, `provider_exists`, `would_lock_out`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "identity"
        ],
        "summary": "Removes a provider saved in the Console: people stop being able to sign in with it.\nIts name must be typed again. Needs `platform.security.manage`; audited.",
        "operationId": "delete_identity_provider",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Provider id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "confirm",
            "in": "query",
            "description": "The provider's name again.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `would_lock_out`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-ins": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Everyone's Apelora sessions open now (or one person's). Needs `user.manage` on the platform.",
        "operationId": "sign_ins",
        "parameters": [
          {
            "name": "user",
            "in": "query",
            "description": "Only this person's.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActiveSignInList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/sign-ins/{id}": {
      "delete": {
        "tags": [
          "identity"
        ],
        "summary": "Ends anyone's session. Needs `user.manage` on the platform.",
        "operationId": "end_sign_in",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Session id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/tenancy": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Organisations, projects and environments the caller can see, with quotas, use and each\nenvironment's Incus project as Incus reports it. Needs `organization.view` or `project.view`\nsomewhere (or `quota.manage`).",
        "operationId": "tenancy",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenancyOverview"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/users": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "People who have signed in, as far as the caller may see them: everyone for a platform\nadministrator, otherwise those with a role in the caller's scopes. Needs `user.view`.",
        "operationId": "users",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/users/lookup": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Finds one person by exact user name or e-mail so a role can be given to them. Someone who has\nnever signed in does not exist yet. Needs `role.assign` or `group.manage`.",
        "operationId": "lookup_user",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Exact user name or e-mail address.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/users/{user}/disable": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Disables a person: their tokens and Apelora sessions stop working at once. Needs\n`user.manage`.",
        "operationId": "disable_user",
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "description": "User id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `last_super_admin`, `self_lockout`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/identity/users/{user}/enable": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Re-enables a person. Needs `user.manage`.",
        "operationId": "enable_user",
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "description": "User id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `last_super_admin`, `self_lockout`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/image-mirrors": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Image mirrors: the configuration this control plane runs with (upstream → mirror pairs and\nwhether only mirrors may be used; URLs, not secrets), whether each mirror answers (probed at\nmost once a minute), and the image servers each deployable catalog class needs with whether\nit is covered. Read-only: configuration stays in the environment. Needs `read-inventory`.",
        "operationId": "image_mirrors",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImageMirrorsReport"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/instances": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "Instances in all projects. Needs `read-inventory`.",
        "operationId": "instances",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "deployment"
        ],
        "summary": "Queues creation of an instance. Needs `deploy`. Apelora marks it as its own; only such\ninstances can later be stopped or deleted through Apelora.",
        "operationId": "create_instance",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Makes the request safe to repeat",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InstanceSpec"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `incus_project_exists`, `quota_exceeded`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`, `incus_project_not_ready`, `quota_unverifiable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/instances/{project}/{name}": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "The instance with the application it belongs to, its recent jobs, and what the caller may\ndo (Start, Stop, Restart, Move and Delete go through the existing instance routes and jobs).",
        "operationId": "instance_page",
        "parameters": [
          {
            "name": "project",
            "in": "path",
            "description": "Incus project.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "description": "Instance name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstancePage"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "deployment"
        ],
        "summary": "Queues deletion of an Apelora instance (stopped first if running). Needs `deploy`.",
        "operationId": "delete_instance",
        "parameters": [
          {
            "name": "project",
            "in": "path",
            "description": "Incus project.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "description": "Instance name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Makes the request safe to repeat",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/instances/{project}/{name}/console-log": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "The end of the instance's console log (`tailKib`, default 64, at most 1024).",
        "operationId": "instance_console_log",
        "parameters": [
          {
            "name": "project",
            "in": "path",
            "description": "Incus project.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "description": "Instance name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tailKib",
            "in": "query",
            "description": "How many KiB from the end of the log (1–1024, default 64).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int32",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceLogText"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/instances/{project}/{name}/logs": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "The instance's log files as Incus lists them (names only).",
        "operationId": "instance_logs",
        "parameters": [
          {
            "name": "project",
            "in": "path",
            "description": "Incus project.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "description": "Instance name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceLogList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/instances/{project}/{name}/logs/{file}": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "The end of one of the instance's log files (`tailKib`, default 64, at most 1024).",
        "operationId": "instance_log",
        "parameters": [
          {
            "name": "project",
            "in": "path",
            "description": "Incus project.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "description": "Instance name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file",
            "in": "path",
            "description": "Log file name, as listed.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tailKib",
            "in": "query",
            "description": "How many KiB from the end of the log (1–1024, default 64).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int32",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceLogText"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/instances/{project}/{name}/move": {
      "get": {
        "tags": [
          "deployment"
        ],
        "summary": "Dry run of moving an instance to another member: whether it keeps running, what it copies,\nwhat blocks it. Changes nothing. Needs `deploy` (or `instance.manage`).",
        "operationId": "preview_instance_move",
        "parameters": [
          {
            "name": "project",
            "in": "path",
            "description": "Incus project.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "description": "Instance name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "target",
            "in": "query",
            "description": "The member to move to.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "allowStop",
            "in": "query",
            "description": "Whether a short stop is acceptable when it cannot move while running.",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MovePreview"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "deployment"
        ],
        "summary": "Moves an Apelora instance to another member, after the check runs again and its name is\ntyped: live when it can, otherwise only with `allowStop`, copying its volumes there.\nQueues an `instance.move` job. Needs `deploy` (or `instance.manage`); audited.",
        "operationId": "move_instance",
        "parameters": [
          {
            "name": "project",
            "in": "path",
            "description": "Incus project.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "description": "Instance name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Makes the request safe to repeat",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MoveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `move_blocked`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/instances/{project}/{name}/state": {
      "post": {
        "tags": [
          "deployment"
        ],
        "summary": "Queues starting or stopping an Apelora instance. Needs `deploy`.",
        "operationId": "change_state",
        "parameters": [
          {
            "name": "project",
            "in": "path",
            "description": "Incus project.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "description": "Instance name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Makes the request safe to repeat",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StateChange"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs": {
      "get": {
        "tags": [
          "deployment"
        ],
        "summary": "Jobs newest first, filtered by status, kind and application and paged with `after`. Whole\nplatform readers (`read-inventory`) see every job; anyone else the jobs of applications they\nmay view.",
        "operationId": "jobs",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "`pending`, `running`, `succeeded`, `failed` or `cancelled`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "description": "Only kinds starting with this, e.g. `instance.` or `volume.restore`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "application",
            "in": "query",
            "description": "Only the jobs of this application.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "after",
            "in": "query",
            "description": "Paging: the `next` of the previous page.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Jobs per page, 1 to 200 (default 100).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobList"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs/{id}": {
      "get": {
        "tags": [
          "deployment"
        ],
        "summary": "A queued job and its progress. Needs `read-inventory`.",
        "operationId": "job",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Job id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs/{id}/cancel": {
      "post": {
        "tags": [
          "deployment"
        ],
        "summary": "Cancels a job. A waiting job with nothing in flight is cancelled at once (`cancelled`);\notherwise the request is recorded (`requested`) and the worker stops at the job kind's next\nsafe point, never in the middle of an Incus change (see `safePoints` on the job's detail).\nRepeating the request changes nothing. Refused (409 `job_finished`) for a finished job. Needs\nthe permission that queues that kind of job on its target; audited.",
        "operationId": "cancel_job",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Job id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobCancellation"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `job_finished`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs/{id}/detail": {
      "get": {
        "tags": [
          "deployment"
        ],
        "summary": "A job with its attempts (worker, timings, outcome, error and the Incus operations each\nstarted), who queued it, its request id, and the jobs linked to it (retries, and other jobs\nthe same request queued). Same visibility as `GET /api/v1/jobs/{id}`.",
        "operationId": "job_detail",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Job id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobDetail"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs/{id}/retry": {
      "post": {
        "tags": [
          "deployment"
        ],
        "summary": "Queues a new job that repeats a failed one, linked to it (`retryOf`); the failed job is kept\nunchanged as evidence. Needs the permission that queues that kind of job on its target.\nRefused (409) when the job did not fail (`not_failed`), was retried already\n(`already_retried`), a newer job for the same target was queued since (`superseded`), or it\nis an application operation (`not_retryable`: start it again from the application). Audited.",
        "operationId": "retry_job",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Job id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Makes the request safe to repeat",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`, `project_not_allowed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `already_retried`, `not_failed`, `not_retryable`, `superseded`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/machines": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "Machines being enrolled, with their state derived from Incus. Needs `manage-infrastructure`.",
        "operationId": "machines",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MachineList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Registers a machine. A name that is already an eligible member is adopted as admitted.\nNeeds `manage-infrastructure`; audited.",
        "operationId": "register_machine",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterMachine"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Machine"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`, `unknown_machine`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer. `error.code`: `provisioner_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`, `provisioner_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/machines/{name}": {
      "delete": {
        "tags": [
          "cluster"
        ],
        "summary": "Forgets a machine that is not a cluster member (revoking an unused join token). Needs\n`manage-infrastructure`; audited.",
        "operationId": "remove_machine",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Machine name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`, `still_a_member`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/machines/{name}/admission": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "The admission checks for a joined machine (dry run; changes nothing). Needs\n`manage-infrastructure`.",
        "operationId": "preview_machine_admission",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Machine name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Admission"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `not_a_member`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/machines/{name}/admit": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Admits a joined machine: re-runs the admission checks and, when none fails, lets Incus\nplace instances on it. Needs `manage-infrastructure`; audited.",
        "operationId": "admit_machine",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Machine name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Admission"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `admission_blocked`, `not_a_member`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/machines/{name}/approval": {
      "delete": {
        "tags": [
          "cluster"
        ],
        "summary": "Withdraws an approval: revokes the machine's unused join token. Needs\n`manage-infrastructure`; audited.",
        "operationId": "withdraw_machine_approval",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Machine name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/machines/{name}/approve": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Approves a machine: asks Incus for its single-use join token, returned only in this\nresponse with the command to run on the server. Needs `manage-infrastructure`; audited\nwithout the token.",
        "operationId": "approve_machine",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Machine name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MachineApproved"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `already_a_member`, `approval_invalid`, `approval_pending`, `approval_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `cluster_admin_not_configured`, `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/password": {
      "put": {
        "tags": [
          "identity"
        ],
        "summary": "Changes the caller's own password (local accounts only). Every other session of theirs is\nrevoked; the one making the request stays. Counts towards the account's lock like a sign-in.",
        "operationId": "change_password",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasswordChangeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`, `weak_password`, `wrong_password`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `account_locked`, `not_a_local_account`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "500": {
            "description": "Apelora failed; the response's `x-request-id` finds it in the server log. `error.code`: `internal`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/sign-ins": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Your Apelora sessions open now (password and directory sign-ins), most recently used first.\nSign-ins with an identity provider's token are not sessions and are not listed.",
        "operationId": "my_sign_ins",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActiveSignInList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `people_only`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/sign-ins/{id}": {
      "delete": {
        "tags": [
          "identity"
        ],
        "summary": "Ends one of your sessions (signs that browser out). Another person's answers 404.",
        "operationId": "end_my_sign_in",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Session id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `people_only`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/tokens": {
      "get": {
        "tags": [
          "identity"
        ],
        "summary": "Your personal tokens (live ones, and those that ended in the last 30 days), newest first.\nAny signed-in person.",
        "operationId": "my_tokens",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalTokenList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `people_only`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Creates a personal token, shown only in this response. It acts as you with whatever you hold\nwhen it is used, and never opens terminal sessions or makes other credentials. Needs a sign-in\n(not a personal token); 1–365 days, no default; at most 20 live tokens.",
        "operationId": "create_my_token",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePersonalToken"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalTokenCreated"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `people_only`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `too_many_tokens`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/tokens/{id}": {
      "delete": {
        "tags": [
          "identity"
        ],
        "summary": "Revokes one of your live tokens; it stops working at once. Another person's token answers 404.",
        "operationId": "revoke_my_token",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Token id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `people_only`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/tokens/{id}/rotate": {
      "post": {
        "tags": [
          "identity"
        ],
        "summary": "Rotates one of your live tokens: a successor with the same name (shown only in this\nresponse), and the old token keeps working for the overlap (0–1440 minutes, 60 by default),\nthen expires. A token is rotated once; rotate its successor next time.",
        "operationId": "rotate_my_token",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Token id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RotatePersonalToken"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalTokenRotated"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `people_only`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `already_rotated`, `too_many_tokens`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitoring": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Where each metrics endpoint is, whether the caller may scrape, and the region, site and\nsector labels. Needs `fabric.metrics.read` or `cluster.view`.",
        "operationId": "monitoring",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitoringInfo"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/networks": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "Networks in all projects. Needs `read-inventory`.",
        "operationId": "networks",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/networks/applications": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "Each application the caller may view that has a recorded deployment: its network, the\nrules compiled from its design, its service and published addresses, and what Incus holds\nfor each, with the differences. Read-only. Needs `application.view` on each application.",
        "operationId": "application_networks",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetApplications"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/networks/settings": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "The network settings in effect: Apelora's uplink and service range, each deploy project's\nnetwork limits, and the uplink as Incus reports it (with the administrator identity, when\nconfigured), with what does not fit together. Read-only. Needs `cluster.view`.",
        "operationId": "network_settings",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetSettings"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/preflight": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "Read-only readiness checks of the Incus server or cluster, of the projects Apelora deploys\ninto, and of the image mirrors (whether each image server the catalog uses is mirrored and\nwhether the mirrors answer). Changes nothing. Needs `read-inventory`.",
        "operationId": "preflight",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreflightReport"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/projects": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "Incus projects. Needs `read-inventory`.",
        "operationId": "incus_projects",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/provisioners/maas/machines": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "The machines MAAS manages, with the Apelora machine and Incus member each became. Needs\n`cluster.view`. Read-only: MAAS is asked to list, nothing else.",
        "operationId": "maas_machines",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaasMachines"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer. `error.code`: `provisioner_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/provisioners/maas/machines/{systemId}/commission": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Starts commissioning. Needs `hardware.commission` and the hostname typed again. The cloud-init\nof a later deploy is not part of this. Audited; MAAS is asked first.",
        "operationId": "maas_commission",
        "parameters": [
          {
            "name": "systemId",
            "in": "path",
            "description": "MAAS system id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MaasConfirm"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaasAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "500": {
            "description": "Apelora failed; the response's `x-request-id` finds it in the server log. `error.code`: `store_error`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer. `error.code`: `provisioner_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`, `provisioner_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/provisioners/maas/machines/{systemId}/deploy": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Installs an operating system. Needs `hardware.deploy` and the hostname typed again.\n`userData` is sent to MAAS and is not stored or written to the audit log. Audited.",
        "operationId": "maas_deploy",
        "parameters": [
          {
            "name": "systemId",
            "in": "path",
            "description": "MAAS system id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MaasDeploy"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaasAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "500": {
            "description": "Apelora failed; the response's `x-request-id` finds it in the server log. `error.code`: `store_error`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer. `error.code`: `provisioner_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`, `provisioner_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/provisioners/maas/machines/{systemId}/release": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Returns the machine to MAAS's pool. Needs `hardware.deploy` and the hostname typed again.\nDisk erasure needs `hardware.delete` as well and is off unless asked. A secure wipe is not offered.\nAudited; MAAS is asked first.",
        "operationId": "maas_release",
        "parameters": [
          {
            "name": "systemId",
            "in": "path",
            "description": "MAAS system id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MaasRelease"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaasAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "500": {
            "description": "Apelora failed; the response's `x-request-id` finds it in the server log. `error.code`: `store_error`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer. `error.code`: `provisioner_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`, `provisioner_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/provisioners/maas/machines/{systemId}/test": {
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Starts a hardware test run (burn-in) through MAAS. Needs `hardware.commission` and the\nhostname typed again. Only a machine that is `Ready`, `Broken` or `Failed testing`: one that is\nallocated or deployed (an Incus member, for one) is refused, so tests never load a running\nserver. Audited with the test names; MAAS is asked first.",
        "operationId": "maas_test",
        "parameters": [
          {
            "name": "systemId",
            "in": "path",
            "description": "MAAS system id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MaasTest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted: the work is queued; the response says how to follow it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaasAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `machine_in_use`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "500": {
            "description": "Apelora failed; the response's `x-request-id` finds it in the server log. `error.code`: `store_error`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer. `error.code`: `provisioner_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`, `provisioner_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sectors": {
      "get": {
        "tags": [
          "cluster"
        ],
        "summary": "The sectors this control plane knows and whether each answers. Needs `cluster.view`.",
        "operationId": "sectors",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SectorList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "500": {
            "description": "Apelora failed; the response's `x-request-id` finds it in the server log. `error.code`: `invalid_place`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "cluster"
        ],
        "summary": "Registers another Incus cluster as a sector. Stores its name, site, address and the name of\nits credentials; the identity's files stay on the control plane. Needs `cluster.manage`.",
        "operationId": "add_sector",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewSector"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SectorInfo"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`, `invalid_sector`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `sector_exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "500": {
            "description": "Apelora failed; the response's `x-request-id` finds it in the server log. `error.code`: `internal`, `invalid_place`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `no_database`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sectors/{name}": {
      "delete": {
        "tags": [
          "cluster"
        ],
        "summary": "Forgets a registered sector. Nothing changes in its Incus. Needs `cluster.manage`.",
        "operationId": "remove_sector",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "Sector name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "confirm",
            "in": "query",
            "description": "The sector's name, typed again.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `confirmation_mismatch`, `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `no_database`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions": {
      "get": {
        "tags": [
          "sessions"
        ],
        "summary": "Open sessions the caller started, and those on applications they may operate.",
        "operationId": "remote_sessions",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{id}": {
      "delete": {
        "tags": [
          "sessions"
        ],
        "summary": "Ends a session now. Allowed for the person who has it and for whoever may operate its\napplication. Anything else answers 404.",
        "operationId": "end_remote_session",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Session id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller. `error.code`: `not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "The settings this control plane runs with: every setting the control plane and the worker\nread, the value when it may be shown (never a secret, a key or a certificate path), whether\nit is the default and where it came from; sign-in settings saved in the Console; the workers\nseen recently. Needs `cluster.view` on the platform.",
        "operationId": "effective_settings",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EffectiveSettings"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sign-in": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Public. How people can sign in to this control plane.",
        "operationId": "sign_in_options",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignInOptions"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/api/v1/sign-in/password": {
      "post": {
        "tags": [
          "system"
        ],
        "summary": "Public. Signs a person in with a username and password and returns an Apelora session.\nEvery refusal answers `invalid_credentials` (unknown, wrong, locked or disabled alike).\nLimited to 10 attempts a minute per client address.",
        "operationId": "sign_in_with_password",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasswordSignInRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasswordSignInResult"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `directory_unavailable`, `invalid_request`, `local_accounts_disabled`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `account_disabled`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer. `error.code`: `directory_entry_unreadable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`, `directory_unreachable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/api/v1/sign-in/setup": {
      "post": {
        "tags": [
          "system"
        ],
        "summary": "Public. Sets a local account's password with its one-time setup link (24 hours, single\nuse). `setup_invalid` when the link was used, expired or is unknown; `weak_password` with\nthe rule when the password does not follow it.",
        "operationId": "complete_password_setup",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasswordSetupRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`, `setup_invalid`, `weak_password`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "500": {
            "description": "Apelora failed; the response's `x-request-id` finds it in the server log. `error.code`: `internal`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/api/v1/sign-out": {
      "post": {
        "tags": [
          "system"
        ],
        "summary": "Ends the Apelora session the request was made with. With any other credential (an\nidentity-provider or API token) there is nothing to end here: 204.",
        "operationId": "sign_out",
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/orphans": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "Custom volumes in Apelora's projects that no application volume or backup record refers\nto, in every pool, with their size. Read-only: deleting one is a decision made in Incus or,\nfor a kept application volume, on the application. Needs `cluster.view`.",
        "operationId": "orphan_volumes",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrphanList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/pools": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "Storage pools with how full each is, per member and in total (read from each member's\nstate, like the Health page). Read-only. Needs `cluster.view`.",
        "operationId": "storage_pool_usage",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoragePoolReport"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "A service Apelora relies on (Incus, an identity provider, a provisioner) refused or did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/volumes": {
      "get": {
        "tags": [
          "inventory"
        ],
        "summary": "Every application volume the caller may see, with what Incus reports, its schedules and\nhow many backups it has. Read-only. Needs `application.view` on each application.",
        "operationId": "storage_volumes",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageVolumeList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support-bundle": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Downloads a support bundle (a tar file, streamed): manifest, versions, effective settings\n(secrets never included), health, preflight, jobs that failed in the last 24 hours with their\nattempts, a metrics snapshot and where to find logs. Never tokens, passwords, certificates or\nkeys. Needs `support.bundle`; audited (`support.bundle.downloaded`) before it is sent.",
        "operationId": "support_bundle",
        "responses": {
          "200": {
            "description": "A tar archive",
            "content": {
              "application/x-tar": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/system": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Versions of this control plane and the Incus release it is pinned to, and when the\ncertificates Apelora uses to reach Incus expire, and Incus as observed now (running version,\nor the error that keeps it unreachable). Needs `read-inventory`.",
        "operationId": "system",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemInfo"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tokens": {
      "get": {
        "tags": [
          "administration"
        ],
        "summary": "API tokens, active and revoked (never the tokens themselves). Needs `manage-tokens`.",
        "operationId": "tokens",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenList"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "administration"
        ],
        "summary": "Creates an API token, shown only in this response. Needs `manage-tokens` and every permission\nthe token's role carries (a token never does more than its creator). A `fabric-admin` token\nalso needs another person's approval of `token.create_admin` on `token:fabric-admin`, sent as\n`Apelora-Approval`; an API token cannot present one, so it cannot create `fabric-admin` tokens.",
        "operationId": "create_token",
        "parameters": [
          {
            "name": "Apelora-Approval",
            "in": "header",
            "description": "For a fabric-admin token: the approval another person granted for token.create_admin on token:fabric-admin",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateToken"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the response describes what was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenCreated"
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the error says which part. `error.code`: `invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `approval_unavailable`, `forbidden`, `mfa_required`, `token_exceeds_caller`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with the current state; the error code says how. `error.code`: `approval_invalid`, `approval_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tokens/{id}": {
      "delete": {
        "tags": [
          "administration"
        ],
        "summary": "Revokes an API token; it stops working at once. Needs `manage-tokens`.",
        "operationId": "revoke_token",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Token id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Done; nothing is returned."
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Something this needs is not configured or not reachable yet; the error code says what. `error.code`: `database_not_configured`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whoami": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Who is calling, with the role assignments and permissions in force.",
        "operationId": "whoami",
        "responses": {
          "200": {
            "description": "Done; the response holds the result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhoAmI"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/metrics": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Metrics of this control plane in the text exposition format (OpenMetrics when the `Accept`\nheader asks for `application/openmetrics-text`). Needs `fabric.metrics.read` (built-in role\nMetrics Reader, for the collector's service identity). Labels never carry names, ids, paths\nwith ids, tokens or error texts; see docs/architecture/MONITORING.md.",
        "operationId": "metrics",
        "responses": {
          "200": {
            "description": "Metrics in the text exposition format",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in: no token, or one that is unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not do this. `error.code`: `forbidden`, `mfa_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address or caller; retry after `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before trying again."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AccessList": {
        "type": "object",
        "required": [
          "items",
          "observed",
          "provider",
          "idleSecs",
          "maxSecs"
        ],
        "properties": {
          "idleSecs": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InstanceAccess"
            }
          },
          "maxSecs": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "observed": {
            "type": "boolean",
            "description": "Incus could be read just now. When false, `items` is empty and nothing may be opened."
          },
          "provider": {
            "$ref": "#/components/schemas/ProviderMode"
          }
        }
      },
      "ActionState": {
        "type": "object",
        "required": [
          "allowed"
        ],
        "properties": {
          "allowed": {
            "type": "boolean"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why not, in a sentence the interface can show."
          }
        }
      },
      "Actions": {
        "type": "object",
        "required": [
          "start",
          "stop",
          "shutdown",
          "restart",
          "migrate"
        ],
        "properties": {
          "migrate": {
            "$ref": "#/components/schemas/ActionState",
            "description": "Move every instance to another server."
          },
          "restart": {
            "$ref": "#/components/schemas/ActionState"
          },
          "shutdown": {
            "$ref": "#/components/schemas/ActionState",
            "description": "Graceful: each guest is asked to shut down and given time to."
          },
          "start": {
            "$ref": "#/components/schemas/ActionState"
          },
          "stop": {
            "$ref": "#/components/schemas/ActionState",
            "description": "Immediate power-off: nothing waits for the guests to shut down."
          }
        }
      },
      "ActiveSignIn": {
        "type": "object",
        "required": [
          "id",
          "userId",
          "person",
          "method",
          "createdAt",
          "lastUsedAt",
          "expiresAt",
          "endsAt",
          "current"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "current": {
            "type": "boolean",
            "description": "The request was made with this session."
          },
          "endsAt": {
            "type": "string",
            "format": "date-time",
            "description": "When it ends unless it is used again (an hour without use, or the absolute limit)."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "The absolute limit (eight hours after sign-in)."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The session id (never its token)."
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time"
          },
          "method": {
            "type": "string",
            "description": "`password` (local account) or `directory`."
          },
          "person": {
            "type": "string"
          },
          "userId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "ActiveSignInList": {
        "type": "object",
        "required": [
          "items",
          "credential",
          "idleSecs",
          "absoluteSecs"
        ],
        "properties": {
          "absoluteSecs": {
            "type": "integer",
            "format": "int64",
            "description": "A session ends this many seconds after sign-in, however busy."
          },
          "credential": {
            "type": "string",
            "description": "How this request was made (see `WhoAmI::credential`). With `identity-provider`, the\ncurrent sign-in is not in the list: the provider's token is not a session Apelora holds."
          },
          "idleSecs": {
            "type": "integer",
            "format": "int64",
            "description": "A session ends after this many seconds without use."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActiveSignIn"
            }
          }
        }
      },
      "Admission": {
        "type": "object",
        "required": [
          "source",
          "name",
          "admissible",
          "checks"
        ],
        "properties": {
          "admissible": {
            "type": "boolean",
            "description": "No check failed: the machine can be admitted."
          },
          "checks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Check"
            }
          },
          "name": {
            "type": "string"
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "AlertAcknowledgeRequest": {
        "type": "object",
        "properties": {
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "What is being done about it (at most 500 characters)."
          }
        },
        "additionalProperties": false
      },
      "AlertAcknowledgement": {
        "type": "object",
        "description": "Who acknowledged an alert.",
        "required": [
          "by",
          "at"
        ],
        "properties": {
          "at": {
            "type": "string",
            "description": "RFC 3339."
          },
          "by": {
            "type": "string",
            "description": "`user:<id>`, `service:<id>` or `token:<name>`."
          },
          "byName": {
            "type": [
              "string",
              "null"
            ]
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "AlertActions": {
        "type": "object",
        "description": "What the caller may do here.",
        "required": [
          "respond",
          "configure"
        ],
        "properties": {
          "configure": {
            "$ref": "#/components/schemas/ActionState",
            "description": "Change rules and channels (`alert.configure`)."
          },
          "respond": {
            "$ref": "#/components/schemas/ActionState",
            "description": "Acknowledge and silence (`alert.respond`)."
          }
        }
      },
      "AlertChannel": {
        "type": "object",
        "description": "A webhook channel.",
        "required": [
          "id",
          "name",
          "kind",
          "host",
          "secretRef",
          "enabled",
          "minSeverity",
          "delivery",
          "createdAt",
          "createdBy",
          "updatedAt"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string"
          },
          "delivery": {
            "$ref": "#/components/schemas/AlertChannelDelivery"
          },
          "enabled": {
            "type": "boolean"
          },
          "host": {
            "type": "string",
            "description": "The host it posts to."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "description": "`webhook`."
          },
          "minSeverity": {
            "$ref": "#/components/schemas/AlertSeverity"
          },
          "name": {
            "type": "string"
          },
          "secretRef": {
            "type": "string",
            "description": "The name of the environment variable on the worker that holds the signing secret."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "The full URL, only for callers who may configure channels (it may carry a token)."
          }
        }
      },
      "AlertChannelDelivery": {
        "type": "object",
        "description": "A channel's deliveries, from its outbox messages (kept a week after delivery).",
        "required": [
          "pending",
          "failing"
        ],
        "properties": {
          "failing": {
            "type": "integer",
            "format": "int64"
          },
          "lastDeliveredAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "RFC 3339."
          },
          "lastError": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the newest still-failing message failed."
          },
          "pending": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "AlertChannelList": {
        "type": "object",
        "required": [
          "items",
          "secretPrefix",
          "actions"
        ],
        "properties": {
          "actions": {
            "$ref": "#/components/schemas/AlertActions"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertChannel"
            }
          },
          "secretPrefix": {
            "type": "string",
            "description": "What a secret reference must start with."
          }
        }
      },
      "AlertChannelRequest": {
        "type": "object",
        "required": [
          "name",
          "url",
          "secretRef"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "minSeverity": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/AlertSeverity",
                "description": "Alerts of this severity and above are sent (default `warning`)."
              },
              {
                "type": "null"
              }
            ]
          },
          "name": {
            "type": "string",
            "description": "1 to 80 characters, unique."
          },
          "secretRef": {
            "type": "string",
            "description": "The name of the environment variable on the worker holding the signing secret, e.g.\n`APELORA_ALERT_SECRET_OPS`. Never the secret itself."
          },
          "url": {
            "type": "string",
            "description": "`https://…` only, without a user name or password."
          }
        },
        "additionalProperties": false
      },
      "AlertChannelTest": {
        "type": "object",
        "description": "A channel test was queued.",
        "required": [
          "messageId"
        ],
        "properties": {
          "messageId": {
            "type": "integer",
            "format": "int64",
            "description": "The outbox message (`Apelora-Event-Id` at the receiver)."
          }
        }
      },
      "AlertComparison": {
        "type": "string",
        "description": "How a rule compares its value with the threshold.",
        "enum": [
          "at-least",
          "at-most"
        ]
      },
      "AlertCounts": {
        "type": "object",
        "description": "Firing alerts by severity, and those nobody has acknowledged or silenced.",
        "required": [
          "critical",
          "warning",
          "info",
          "needsAttention"
        ],
        "properties": {
          "critical": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "info": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "needsAttention": {
            "type": "integer",
            "format": "int32",
            "description": "Firing, not acknowledged and not silenced: what needs attention.",
            "minimum": 0
          },
          "warning": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "AlertEvaluator": {
        "type": "object",
        "description": "Whether the worker's evaluator is running.",
        "required": [
          "stale",
          "message"
        ],
        "properties": {
          "durationSecs": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "everySecs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "lastPassAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "RFC 3339; `None` when no worker has evaluated alerts yet."
          },
          "message": {
            "type": "string",
            "description": "What the state means, in a sentence."
          },
          "stale": {
            "type": "boolean",
            "description": "No pass for more than three intervals (or none ever): alerts may be out of date."
          },
          "worker": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "AlertHistory": {
        "type": "object",
        "description": "Resolved alerts, newest first.",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertItem"
            }
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass this as `after` for the next, older page; absent on the last page."
          }
        }
      },
      "AlertItem": {
        "type": "object",
        "description": "One alert, firing or resolved.",
        "required": [
          "id",
          "rule",
          "title",
          "subject",
          "severity",
          "state",
          "summary",
          "value",
          "threshold",
          "comparison",
          "unit",
          "startedAt",
          "lastSeenAt",
          "runbook"
        ],
        "properties": {
          "acknowledged": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/AlertAcknowledgement"
              },
              {
                "type": "null"
              }
            ]
          },
          "clearingSince": {
            "type": [
              "string",
              "null"
            ],
            "description": "Firing, but the condition has been clear since this time (it resolves once it stays\nclear for the rule's duration)."
          },
          "comparison": {
            "$ref": "#/components/schemas/AlertComparison"
          },
          "firedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "resolvedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "rule": {
            "type": "string"
          },
          "runbook": {
            "type": "string",
            "description": "Where the operator runbooks explain this alert: a page and section, e.g.\n`alerts.md#jobs-are-failing`."
          },
          "severity": {
            "$ref": "#/components/schemas/AlertSeverity"
          },
          "silencedBy": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/AlertSilencedBy"
              },
              {
                "type": "null"
              }
            ]
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339: when the condition was first seen, when it fired, last seen holding, resolved."
          },
          "state": {
            "type": "string",
            "description": "`firing` or `resolved`."
          },
          "subject": {
            "type": "string",
            "description": "What it is about: a job kind, a worker, a member, `project/instance`, …"
          },
          "summary": {
            "type": "string"
          },
          "threshold": {
            "type": "number",
            "format": "double"
          },
          "title": {
            "type": "string"
          },
          "unit": {
            "type": "string"
          },
          "value": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "AlertList": {
        "type": "object",
        "description": "Open alerts (firing; pending ones are not shown), silences in force, counts and the\nevaluator's state.",
        "required": [
          "alerts",
          "silences",
          "counts",
          "evaluator",
          "actions"
        ],
        "properties": {
          "actions": {
            "$ref": "#/components/schemas/AlertActions"
          },
          "alerts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertItem"
            }
          },
          "counts": {
            "$ref": "#/components/schemas/AlertCounts"
          },
          "evaluator": {
            "$ref": "#/components/schemas/AlertEvaluator"
          },
          "silences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertSilence"
            }
          }
        }
      },
      "AlertRuleItem": {
        "type": "object",
        "description": "A built-in rule with its parameters in force.",
        "required": [
          "id",
          "title",
          "description",
          "unit",
          "comparison",
          "thresholdEditable",
          "thresholdMin",
          "thresholdMax",
          "params",
          "defaults",
          "source",
          "sourceState",
          "firing",
          "runbook"
        ],
        "properties": {
          "comparison": {
            "$ref": "#/components/schemas/AlertComparison"
          },
          "defaults": {
            "$ref": "#/components/schemas/AlertRuleParams"
          },
          "description": {
            "type": "string"
          },
          "firing": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "id": {
            "type": "string"
          },
          "params": {
            "$ref": "#/components/schemas/AlertRuleParams"
          },
          "runbook": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "description": "Where its facts come from."
          },
          "sourceState": {
            "type": "string",
            "description": "What the evaluator's last pass said about that source: `ok`, `not-configured`,\n`unavailable`, `disabled`, or `unknown` before the first pass."
          },
          "thresholdEditable": {
            "type": "boolean",
            "description": "`false`: the rule fires while a state lasts; only its duration and severity are tuned."
          },
          "thresholdMax": {
            "type": "number",
            "format": "double"
          },
          "thresholdMin": {
            "type": "number",
            "format": "double"
          },
          "title": {
            "type": "string"
          },
          "unit": {
            "type": "string"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "RFC 3339 and who, when an operator changed it."
          },
          "updatedBy": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "AlertRuleList": {
        "type": "object",
        "required": [
          "items",
          "actions"
        ],
        "properties": {
          "actions": {
            "$ref": "#/components/schemas/AlertActions"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertRuleItem"
            }
          }
        }
      },
      "AlertRuleParams": {
        "type": "object",
        "description": "A rule's parameters.",
        "required": [
          "enabled",
          "threshold",
          "forSecs",
          "severity"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "forSecs": {
            "type": "integer",
            "format": "int32",
            "description": "Seconds the condition must hold before firing, and stay clear before resolving.",
            "minimum": 0
          },
          "severity": {
            "$ref": "#/components/schemas/AlertSeverity"
          },
          "threshold": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "AlertSeverity": {
        "type": "string",
        "enum": [
          "info",
          "warning",
          "critical"
        ]
      },
      "AlertSilence": {
        "type": "object",
        "description": "A silence in force.",
        "required": [
          "id",
          "rule",
          "ruleTitle",
          "startsAt",
          "endsAt",
          "note",
          "createdBy"
        ],
        "properties": {
          "createdBy": {
            "type": "string"
          },
          "createdByName": {
            "type": [
              "string",
              "null"
            ]
          },
          "endsAt": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "note": {
            "type": "string"
          },
          "rule": {
            "type": "string"
          },
          "ruleTitle": {
            "type": "string"
          },
          "startsAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "subject": {
            "type": [
              "string",
              "null"
            ],
            "description": "`None`: every subject of the rule."
          }
        }
      },
      "AlertSilenceRequest": {
        "type": "object",
        "required": [
          "rule",
          "minutes"
        ],
        "properties": {
          "minutes": {
            "type": "integer",
            "format": "int32",
            "description": "1 to 10080 (a week).",
            "minimum": 0
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "rule": {
            "type": "string"
          },
          "subject": {
            "type": [
              "string",
              "null"
            ],
            "description": "One subject; absent: every subject of the rule."
          }
        },
        "additionalProperties": false
      },
      "AlertSilencedBy": {
        "type": "object",
        "description": "The silence that holds back an alert's notifications.",
        "required": [
          "id",
          "until"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "until": {
            "type": "string",
            "description": "RFC 3339."
          }
        }
      },
      "ApiTokenSetting": {
        "type": "object",
        "required": [
          "enabled",
          "lockedByEnvironment"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "lockedByEnvironment": {
            "type": "boolean",
            "description": "Turned off by `APELORA_LEGACY_TOKENS=disabled`: it cannot be turned on here."
          }
        }
      },
      "ApiTokensRequest": {
        "type": "object",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "ApplicationDetail": {
        "type": "object",
        "required": [
          "application",
          "modules",
          "versions",
          "operations"
        ],
        "properties": {
          "application": {
            "$ref": "#/components/schemas/ApplicationInfo"
          },
          "modules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModuleDetail"
            }
          },
          "operations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OperationDto"
            }
          },
          "versions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VersionInfo"
            }
          }
        }
      },
      "ApplicationInfo": {
        "type": "object",
        "required": [
          "name",
          "createdAt",
          "updatedAt",
          "description",
          "icon",
          "project",
          "archived",
          "design",
          "deployment",
          "actions"
        ],
        "properties": {
          "actions": {
            "$ref": "#/components/schemas/Actions",
            "description": "What the caller may do now, from their permissions and the application's state."
          },
          "archived": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "deployment": {
            "$ref": "#/components/schemas/DeploymentInfo"
          },
          "description": {
            "type": "string"
          },
          "design": {
            "$ref": "#/components/schemas/DesignInfo"
          },
          "environment": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/EnvironmentRef"
              },
              {
                "type": "null"
              }
            ]
          },
          "icon": {
            "type": "string",
            "description": "Key of the icon (a catalog icon such as `nginx`, or a generic one such as `generic-box`)."
          },
          "latestRevision": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "project": {
            "$ref": "#/components/schemas/ProjectRef"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ApplicationList": {
        "type": "object",
        "required": [
          "items",
          "observedAt",
          "stale"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationInfo"
            }
          },
          "observedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When Incus was observed for these statuses (RFC 3339), and whether that failed."
          },
          "stale": {
            "type": "boolean"
          }
        }
      },
      "ApplicationStatus": {
        "type": "object",
        "required": [
          "source",
          "items",
          "services"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModuleStatus"
            }
          },
          "services": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceStatus"
            },
            "description": "Allocated service addresses (empty without a database or service range)."
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          },
          "trafficBlocked": {
            "type": [
              "string",
              "null"
            ],
            "description": "Present while the application's service addresses cannot move traffic to replacement\nreplicas because Incus refuses load balancer changes (a cluster member is unreachable):\nwhat happens, which member, and what to do."
          }
        }
      },
      "ApplicationVolumes": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VolumeItem"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "ApprovalDto": {
        "type": "object",
        "required": [
          "id",
          "action",
          "target",
          "requester",
          "state",
          "reason",
          "createdAt",
          "expiresAt"
        ],
        "properties": {
          "action": {
            "type": "string"
          },
          "approver": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "reason": {
            "type": "string"
          },
          "requester": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "description": "`pending`, `approved`, `rejected`, `cancelled` or `consumed`."
          },
          "target": {
            "type": "string"
          }
        }
      },
      "ApprovalList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApprovalDto"
            }
          }
        }
      },
      "AssignmentDto": {
        "type": "object",
        "required": [
          "id",
          "principal",
          "role",
          "roleName",
          "scope",
          "conditions",
          "kind",
          "createdBy",
          "createdAt"
        ],
        "properties": {
          "conditions": {
            "$ref": "#/components/schemas/Conditions"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "$ref": "#/components/schemas/AssignmentKind"
          },
          "principal": {
            "$ref": "#/components/schemas/PrincipalRef"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "revokedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "role": {
            "$ref": "#/components/schemas/RoleRef"
          },
          "roleName": {
            "type": "string"
          },
          "scope": {
            "$ref": "#/components/schemas/Scope"
          }
        }
      },
      "AssignmentKind": {
        "type": "string",
        "enum": [
          "standard",
          "emergency"
        ]
      },
      "AssignmentList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AssignmentDto"
            }
          }
        }
      },
      "AssignmentPreview": {
        "type": "object",
        "required": [
          "allowed",
          "before",
          "after",
          "added",
          "inert",
          "warnings"
        ],
        "properties": {
          "added": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Permissions the assignment adds."
          },
          "after": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EffectivePermission"
            },
            "description": "What they could do once this assignment exists (the new grant has the nil assignment id)."
          },
          "allowed": {
            "type": "boolean",
            "description": "Could the signed-in administrator save this assignment?"
          },
          "before": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EffectivePermission"
            },
            "description": "What the person can already do at that scope."
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why not, when `allowed` is false."
          },
          "inert": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Permissions in the role that do nothing at this scope."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "AuditItem": {
        "type": "object",
        "required": [
          "id",
          "at",
          "actor",
          "actorType",
          "action",
          "target",
          "outcome",
          "detail"
        ],
        "properties": {
          "action": {
            "type": "string"
          },
          "actor": {
            "type": "string",
            "description": "Stable id of who acted, e.g. `user:<uuid>`, `service:<uuid>`, `token:<name>`."
          },
          "actorName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The name the actor had when they acted (a username, a token's or service identity's\nname); absent on events recorded before names were kept."
          },
          "actorType": {
            "type": "string",
            "description": "`user`, `service`, `token`, `development`, `cli`, `system`, or `anonymous` (a failed\npassword sign-in for an unknown username)."
          },
          "at": {
            "type": "string",
            "description": "RFC 3339 timestamp."
          },
          "detail": {
            "type": "object",
            "description": "What the action changed or was refused, in fields that depend on the action."
          },
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "outcome": {
            "type": "string",
            "description": "`success`, `denied` or `failed`."
          },
          "scope": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/AuditScope",
                "description": "The organisation, project and application the event concerns, when it concerns any."
              },
              {
                "type": "null"
              }
            ]
          },
          "target": {
            "type": "string"
          }
        }
      },
      "AuditList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditItem"
            }
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass this as `after` for the next, older page; absent on the last page."
          }
        }
      },
      "AuditScope": {
        "type": "object",
        "description": "The ids of the organisation, project and application an audit event concerns.",
        "properties": {
          "application": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "organization": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "project": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "AuthMode": {
        "type": "string",
        "enum": [
          "tokens",
          "disabled-development"
        ]
      },
      "Availability": {
        "type": "string",
        "description": "How a module may be run and recovered (from its catalog class).",
        "enum": [
          "stateless",
          "singleton",
          "stateful"
        ]
      },
      "BackupAssessment": {
        "type": "object",
        "required": [
          "state",
          "findings"
        ],
        "properties": {
          "backupAgeHours": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "drillAgeDays": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "findings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BackupFinding"
            },
            "description": "Every reason the state is not `ok`, worst first; one line saying so when it is."
          },
          "state": {
            "$ref": "#/components/schemas/BackupState"
          }
        }
      },
      "BackupFinding": {
        "type": "object",
        "required": [
          "level",
          "text"
        ],
        "properties": {
          "level": {
            "$ref": "#/components/schemas/BackupState"
          },
          "text": {
            "type": "string"
          }
        }
      },
      "BackupInfo": {
        "type": "object",
        "description": "The manifest next to a dump (`apelora-db-backup/1`), as far as the Console shows it.",
        "required": [
          "file",
          "createdAt",
          "sizeBytes",
          "encryption",
          "pgDumpVersion",
          "durationSeconds"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "durationSeconds": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "encryption": {
            "type": "string",
            "description": "`none`, or how the dump is encrypted (`age`, `cms`)."
          },
          "file": {
            "type": "string"
          },
          "migrations": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Migrations the database had when it was dumped.",
            "minimum": 0
          },
          "pgDumpVersion": {
            "type": "string"
          },
          "sizeBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          }
        }
      },
      "BackupState": {
        "type": "string",
        "enum": [
          "ok",
          "warning",
          "failing"
        ]
      },
      "Capabilities": {
        "type": "object",
        "description": "What a provisioner can do to a machine without someone at the server.",
        "required": [
          "discovers",
          "installs",
          "powers"
        ],
        "properties": {
          "discovers": {
            "type": "boolean"
          },
          "installs": {
            "type": "boolean"
          },
          "powers": {
            "type": "boolean"
          }
        }
      },
      "CapacityReport": {
        "type": "object",
        "description": "Free capacity of the cluster for the Studio: per server and in total.",
        "required": [
          "source",
          "named",
          "volumePoolShared",
          "servers",
          "totals"
        ],
        "properties": {
          "named": {
            "type": "boolean",
            "description": "Server names are shown (the caller holds `cluster.view`); otherwise servers are numbered."
          },
          "servers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CapacityServer"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          },
          "totals": {
            "$ref": "#/components/schemas/CapacityTotals"
          },
          "volumePool": {
            "type": [
              "string",
              "null"
            ],
            "description": "The pool volumes are created in; `null`: designs with volumes cannot be deployed."
          },
          "volumePoolShared": {
            "type": "boolean",
            "description": "The volume pool is one pool all servers share (its free space is one budget, not one\nper server)."
          }
        }
      },
      "CapacityServer": {
        "type": "object",
        "description": "One server's free capacity, as the Studio compares it with a design.",
        "required": [
          "label",
          "acceptsModules",
          "architecture"
        ],
        "properties": {
          "acceptsModules": {
            "type": "boolean",
            "description": "Online, not held out of placement, and its resources could be read."
          },
          "architecture": {
            "type": "string"
          },
          "cpuThreads": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "label": {
            "type": "string",
            "description": "The server's name for callers with `cluster.view`; otherwise `Server 1`, `Server 2`, …"
          },
          "load": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "1-minute load average (clustered servers only)."
          },
          "memory": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/HealthUsage"
              },
              {
                "type": "null"
              }
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it does not accept new modules."
          },
          "volumePool": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/HealthUsage",
                "description": "Space in the pool volumes are created in (`APELORA_VOLUME_POOL`), on this server."
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "CapacityTotals": {
        "type": "object",
        "required": [
          "serversAccepting",
          "cpuThreads",
          "memoryFreeBytes",
          "memoryTotalBytes"
        ],
        "properties": {
          "cpuThreads": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "memoryFreeBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "memoryTotalBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "serversAccepting": {
            "type": "integer",
            "description": "Servers that accept new modules; the sums below are over these.",
            "minimum": 0
          },
          "volumePoolFreeBytes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "`null` when no volume pool is configured. A shared pool (one pool every server uses)\nis counted once.",
            "minimum": 0
          }
        }
      },
      "CertificateStatus": {
        "type": "object",
        "required": [
          "certificate",
          "expiresAt",
          "daysLeft",
          "state"
        ],
        "properties": {
          "certificate": {
            "type": "string",
            "description": "`deploy` (restricted client identity), `admin` (unrestricted client identity) or\n`server` (the pinned Incus server certificate)."
          },
          "daysLeft": {
            "type": "integer",
            "format": "int64",
            "description": "Whole days left; negative once expired."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "state": {
            "type": "string",
            "description": "`ok`, `expiring` (within 30 days) or `expired`."
          }
        }
      },
      "ChangeSettings": {
        "type": "object",
        "description": "A change to cluster settings: each key is one of the listed settings; an empty or null value\nremoves it so Incus's default applies again.",
        "required": [
          "changes"
        ],
        "properties": {
          "changes": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "null"
              ]
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "dryRun": {
            "type": "boolean",
            "description": "Only report what would change and what to watch for; nothing is changed and no approval\nis needed."
          }
        }
      },
      "Check": {
        "type": "object",
        "required": [
          "id",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "description": "Stable identifier, e.g. `kernel-version`."
          },
          "status": {
            "$ref": "#/components/schemas/CheckStatus"
          },
          "title": {
            "type": "string"
          }
        }
      },
      "CheckRequest": {
        "type": "object",
        "required": [
          "issuer"
        ],
        "properties": {
          "issuer": {
            "type": "string"
          }
        }
      },
      "CheckStatus": {
        "type": "string",
        "enum": [
          "pass",
          "not-checked",
          "warn",
          "fail"
        ]
      },
      "CheckedEntry": {
        "type": "object",
        "description": "What the check found for the test person.",
        "required": [
          "dn",
          "subject",
          "username",
          "groups",
          "mappedGroups"
        ],
        "properties": {
          "displayName": {
            "type": [
              "string",
              "null"
            ]
          },
          "dn": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The person's groups: each group's full DN (normalized), or a value that is not a DN."
          },
          "mappedGroups": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Apelora groups mapped to this directory (`directory`) and to one of `groups`; empty for\nsettings not saved yet."
          },
          "subject": {
            "type": "string",
            "description": "The stable id Apelora would identify the person by."
          },
          "username": {
            "type": "string"
          }
        }
      },
      "Class": {
        "type": "string",
        "description": "What kind of power a permission is. Only `Tenant` permissions can be granted below the\nplatform level, so an organisation or project role can never reach physical servers,\nthe Incus cluster or the platform's own security settings.",
        "enum": [
          "tenant",
          "infrastructure",
          "security"
        ]
      },
      "ClassImage": {
        "type": "object",
        "description": "An image a class uses, by setting.",
        "required": [
          "class",
          "displayName",
          "alias"
        ],
        "properties": {
          "alias": {
            "type": "string",
            "description": "Alias, or repository with its pinned digest."
          },
          "class": {
            "type": "string",
            "description": "Class id, e.g. `nginx`."
          },
          "displayName": {
            "type": "string"
          },
          "setting": {
            "type": [
              "string",
              "null"
            ],
            "description": "The image-selecting setting, e.g. `channel = stable`."
          }
        }
      },
      "ClusterDatabaseRole": {
        "type": "string",
        "description": "A member's part in the cluster database.",
        "enum": [
          "voter",
          "standby",
          "spare"
        ]
      },
      "ClusterGroupInfo": {
        "type": "object",
        "description": "A cluster group (Incus `/1.0/cluster/groups`): a named set of members that instances and\nprojects can be placed on.",
        "required": [
          "name",
          "description",
          "members"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "members": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "name": {
            "type": "string"
          }
        }
      },
      "ClusterGroupList": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClusterGroupInfo"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "ClusterMember": {
        "type": "object",
        "description": "Observed state of an Incus cluster member (a server in the UI).",
        "required": [
          "name",
          "url",
          "roles",
          "status",
          "message",
          "architecture",
          "failureDomain",
          "database",
          "groups"
        ],
        "properties": {
          "architecture": {
            "type": "string"
          },
          "database": {
            "type": "boolean"
          },
          "failureDomain": {
            "type": "string"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "message": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scheduler": {
            "type": "string",
            "description": "Incus's `scheduler.instance` for this member: `all` (the default), `manual` (only\ninstances targeted at it are placed there) or `group`."
          },
          "status": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        }
      },
      "ClusterMemberDetail": {
        "type": "object",
        "description": "One member with its roles spelled out.",
        "required": [
          "name",
          "status",
          "message",
          "roles",
          "databaseRole",
          "leader",
          "eventHub",
          "ovnChassis",
          "databaseExcluded",
          "upForDatabase",
          "failureDomain",
          "groups",
          "architecture",
          "held",
          "incusVersion",
          "versionError"
        ],
        "properties": {
          "architecture": {
            "type": "string"
          },
          "databaseExcluded": {
            "type": "boolean",
            "description": "Kept out of the cluster database on purpose (`database-client`)."
          },
          "databaseRole": {
            "$ref": "#/components/schemas/ClusterDatabaseRole"
          },
          "eventHub": {
            "type": "boolean",
            "description": "Relays events between members (`event-hub`)."
          },
          "failureDomain": {
            "type": "string"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "held": {
            "type": "boolean",
            "description": "Kept out of automatic placement (`scheduler.instance=manual`)."
          },
          "incusVersion": {
            "type": [
              "string",
              "null"
            ],
            "description": "The Incus release the member runs; `null` when it could not be read."
          },
          "leader": {
            "type": "boolean",
            "description": "Leads the cluster database now."
          },
          "message": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "ovnChassis": {
            "type": "boolean",
            "description": "Runs OVN's chassis role (`ovn-chassis`). Incus lists it only when it was assigned."
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The roles exactly as Incus reports them."
          },
          "status": {
            "type": "string",
            "description": "Incus status: Online, Evacuating, Evacuated, Restoring, Offline or Blocked."
          },
          "upForDatabase": {
            "type": "boolean",
            "description": "Counts towards the database majority: its daemon answers (not Offline or Blocked)."
          },
          "versionError": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the version could not be read."
          }
        }
      },
      "ClusterMembersReport": {
        "type": "object",
        "description": "Members with their roles, the database majority and the Incus release each runs.",
        "required": [
          "source",
          "clustered",
          "members",
          "quorum",
          "versions",
          "sites"
        ],
        "properties": {
          "clustered": {
            "type": "boolean"
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClusterMemberDetail"
            },
            "description": "Empty on a standalone server."
          },
          "powerOffs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PowerOff"
            },
            "description": "Recent BMC power-offs, newest first. Empty when none have been recorded."
          },
          "quorum": {
            "$ref": "#/components/schemas/ClusterQuorum"
          },
          "rebalance": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RebalanceMove"
            },
            "description": "Stateless replicas that share a server. The supervisor moves one only when\n`APELORA_REBALANCE=1`; this list is the dry run."
          },
          "sites": {
            "$ref": "#/components/schemas/SiteReport"
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          },
          "upgrade": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/UpgradeView",
                "description": "The rolling-upgrade assistant. Absent when there is no database."
              },
              {
                "type": "null"
              }
            ]
          },
          "versions": {
            "$ref": "#/components/schemas/ClusterVersions",
            "description": "Version skew against the pinned Incus release, and whether an upgrade could start."
          }
        }
      },
      "ClusterQuorum": {
        "type": "object",
        "description": "The cluster database's majority, now.",
        "required": [
          "state",
          "voters",
          "votersUp",
          "needed",
          "standbys",
          "standbysUp",
          "spares",
          "leader",
          "canLose",
          "summary",
          "nextStep",
          "warnings"
        ],
        "properties": {
          "canLose": {
            "type": "integer",
            "format": "int32",
            "description": "Voters that can be lost at once, now, before changes stop. Incus promotes a stand-by\nwhen a voter goes offline, which raises this again afterwards.",
            "minimum": 0
          },
          "leader": {
            "type": [
              "string",
              "null"
            ]
          },
          "needed": {
            "type": "integer",
            "format": "int32",
            "description": "Voters that must answer for the cluster to accept changes (a majority).",
            "minimum": 0
          },
          "nextStep": {
            "type": [
              "string",
              "null"
            ]
          },
          "spares": {
            "type": "integer",
            "format": "int32",
            "description": "Members holding no copy of the cluster database.",
            "minimum": 0
          },
          "standbys": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "standbysUp": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "state": {
            "$ref": "#/components/schemas/ClusterQuorumState"
          },
          "summary": {
            "type": "string",
            "description": "One sentence for the page."
          },
          "voters": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "votersUp": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ClusterQuorumState": {
        "type": "string",
        "enum": [
          "healthy",
          "at-risk",
          "lost",
          "not-clustered",
          "unknown"
        ]
      },
      "ClusterResponse": {
        "type": "object",
        "required": [
          "source",
          "server",
          "members"
        ],
        "properties": {
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClusterMember"
            },
            "description": "Empty when the Incus server is not clustered."
          },
          "server": {
            "$ref": "#/components/schemas/ServerInfo"
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "ClusterSetting": {
        "type": "object",
        "description": "One cluster setting: its value when set, and Incus's default.",
        "required": [
          "key",
          "label",
          "meaning",
          "value",
          "default",
          "usesDefault"
        ],
        "properties": {
          "default": {
            "type": [
              "string",
              "null"
            ],
            "description": "Incus's default as the server describes it; `null` when it did not say."
          },
          "key": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "meaning": {
            "type": "string"
          },
          "usesDefault": {
            "type": "boolean",
            "description": "Not set, so Incus's default applies."
          },
          "value": {
            "type": [
              "string",
              "null"
            ],
            "description": "The value set in the cluster's configuration; `null` when it is not set."
          }
        }
      },
      "ClusterSettingsReport": {
        "type": "object",
        "required": [
          "source",
          "identity",
          "items"
        ],
        "properties": {
          "identity": {
            "type": "string",
            "description": "The Incus identity the values were read with (`admin`: Incus shows its configuration\nonly to an unrestricted identity)."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClusterSetting"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "ClusterVersionComparison": {
        "type": "string",
        "description": "How a running release compares with the pinned one.",
        "enum": [
          "same",
          "older",
          "newer",
          "unknown"
        ]
      },
      "ClusterVersionGroup": {
        "type": "object",
        "description": "The members running one release.",
        "required": [
          "version",
          "members",
          "againstPin"
        ],
        "properties": {
          "againstPin": {
            "$ref": "#/components/schemas/ClusterVersionComparison"
          },
          "members": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "version": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null`: the members whose version could not be read."
          }
        }
      },
      "ClusterVersionState": {
        "type": "string",
        "enum": [
          "matches-pin",
          "behind-pin",
          "ahead-of-pin",
          "mixed",
          "unknown"
        ]
      },
      "ClusterVersions": {
        "type": "object",
        "description": "Version skew across members and whether a rolling upgrade could start now.",
        "required": [
          "pinned",
          "groups",
          "state",
          "summary",
          "ready",
          "blockers",
          "notes"
        ],
        "properties": {
          "blockers": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What must be fixed before a member is upgraded."
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClusterVersionGroup"
            }
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Facts worth knowing during an upgrade (members in maintenance, blocked members)."
          },
          "pinned": {
            "type": "string",
            "description": "The Incus release Apelora is pinned to (`upstream.lock.yaml`), without the `v`."
          },
          "ready": {
            "type": "boolean",
            "description": "Nothing stands in the way of upgrading the next member."
          },
          "state": {
            "$ref": "#/components/schemas/ClusterVersionState"
          },
          "summary": {
            "type": "string"
          }
        }
      },
      "Conditions": {
        "type": "object",
        "properties": {
          "environments": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/EnvKind"
            },
            "description": "The grant counts only for resources in environments of these kinds."
          },
          "requireMfa": {
            "type": "boolean",
            "description": "The grant counts only when the caller signed in with multi-factor authentication."
          }
        }
      },
      "ConfirmMember": {
        "type": "object",
        "required": [
          "confirm"
        ],
        "properties": {
          "confirm": {
            "type": "string",
            "description": "The member's name again, typed by the administrator."
          },
          "force": {
            "type": "boolean",
            "description": "Evacuate although the dry run found blockers (a workload may lose service). Needs the\nunsafe-evacuation permission and an approval from another person."
          }
        }
      },
      "ConfirmSnapshot": {
        "type": "object",
        "required": [
          "confirm"
        ],
        "properties": {
          "confirm": {
            "type": "string",
            "description": "The snapshot's name again, typed by the person restoring it."
          }
        }
      },
      "Connection": {
        "type": "object",
        "description": "One connection of the design: `from` may reach `to` (module ids).",
        "required": [
          "from",
          "to",
          "transport"
        ],
        "properties": {
          "from": {
            "type": "string"
          },
          "port": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "`None`: any port of the transport (the protocol has no well-known port).",
            "minimum": 0
          },
          "to": {
            "type": "string"
          },
          "transport": {
            "type": "string",
            "description": "`tcp` or `udp`."
          }
        }
      },
      "CoverageKind": {
        "type": "string",
        "description": "What happens to images from a server here.",
        "enum": [
          "mirrored",
          "upstream",
          "refused"
        ]
      },
      "CreateApplication": {
        "type": "object",
        "required": [
          "name",
          "environmentId"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "document": {
            "type": [
              "object",
              "null"
            ],
            "description": "The first draft (a Studio document), if any."
          },
          "environmentId": {
            "type": "string",
            "format": "uuid",
            "description": "The environment (and so the project) the application lives in."
          },
          "icon": {
            "type": [
              "string",
              "null"
            ],
            "description": "Icon key; `box` when omitted."
          },
          "name": {
            "type": "string",
            "description": "Lowercase letters, digits and hyphens, starting with a letter; at most 40 characters. Fixed\nfor the life of the application (instances are named after it)."
          }
        }
      },
      "CreateJoinToken": {
        "type": "object",
        "required": [
          "memberName"
        ],
        "properties": {
          "memberName": {
            "type": "string",
            "description": "Name the new member will join with."
          }
        }
      },
      "CreatePersonalToken": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "expiresInDays": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "1–365 days; required."
          },
          "name": {
            "type": "string",
            "description": "What it is for, e.g. \"laptop backup script\"."
          }
        }
      },
      "CreateToken": {
        "type": "object",
        "required": [
          "name",
          "role"
        ],
        "properties": {
          "expiresInDays": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "1–365 days; 90 when omitted."
          },
          "name": {
            "type": "string",
            "description": "Who or what uses it, e.g. \"ci\" or a person's name."
          },
          "role": {
            "$ref": "#/components/schemas/Role"
          }
        }
      },
      "DatabaseBackupReport": {
        "type": "object",
        "required": [
          "configured",
          "backups"
        ],
        "properties": {
          "assessment": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/BackupAssessment"
              },
              {
                "type": "null"
              }
            ]
          },
          "backups": {
            "type": "integer",
            "description": "How many backup manifests the directory holds.",
            "minimum": 0
          },
          "configured": {
            "type": "boolean",
            "description": "`APELORA_DB_BACKUP_DIR` is set. When false, nothing else is known."
          },
          "directory": {
            "type": [
              "string",
              "null"
            ],
            "description": "The directory the records are read from."
          },
          "lastDrill": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/DrillInfo",
                "description": "The latest restore drill, whether it passed or failed."
              },
              {
                "type": "null"
              }
            ]
          },
          "lastVerified": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/DrillInfo",
                "description": "The latest drill that passed."
              },
              {
                "type": "null"
              }
            ]
          },
          "newestBackup": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/BackupInfo"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "DeployRequest": {
        "type": "object",
        "required": [
          "project",
          "document",
          "modules"
        ],
        "properties": {
          "confirmDisruption": {
            "type": "boolean",
            "description": "Required when the plan rebuilds a singleton or stateful module (`rebuild`): it\nacknowledges that the module is stopped while it is rebuilt. Data on volumes is kept."
          },
          "connections": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/Connection"
            },
            "description": "The design's connections; enforced when the control plane has a network uplink."
          },
          "document": {
            "type": "object",
            "description": "The Studio document, saved as an immutable revision. Ignored when `version` is given."
          },
          "modules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DesiredModule"
            }
          },
          "project": {
            "type": "string"
          },
          "published": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Published"
            },
            "description": "Ports reachable from outside the application (needs connections to be enforced)."
          },
          "removeMissing": {
            "type": "boolean",
            "description": "Also delete the application's instances that are no longer in the design."
          },
          "version": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Deploy this published version (its stored document) instead of saving `document` as a\nnew revision. Drafts can never be deployed."
          }
        }
      },
      "DeployResponse": {
        "type": "object",
        "required": [
          "application",
          "revision",
          "plan",
          "jobs"
        ],
        "properties": {
          "application": {
            "type": "string"
          },
          "jobs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QueuedChange"
            }
          },
          "networkJob": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The job that applies the connections to the application's network, when enforced."
          },
          "operation": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The rolling update that replaces the plan's `replace` instances one replica at a time,\neach new one healthy before the old one goes (an application operation of kind\n`update`); absent when nothing is replaced."
          },
          "plan": {
            "$ref": "#/components/schemas/Plan",
            "description": "The plan that was applied (recomputed when applying)."
          },
          "revision": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "DeploymentInfo": {
        "type": "object",
        "required": [
          "status",
          "observedAt",
          "stale",
          "source",
          "modules",
          "replicas"
        ],
        "properties": {
          "deployedVersion": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "The published version the application was last deployed from."
          },
          "lastActivityAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "modules": {
            "type": "integer",
            "format": "int32",
            "description": "Modules in the deployed version; 0 until a version is deployed.",
            "minimum": 0
          },
          "observedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the control plane last observed Incus for this answer (RFC 3339)."
          },
          "operation": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/OperationSummary"
              },
              {
                "type": "null"
              }
            ]
          },
          "replicas": {
            "$ref": "#/components/schemas/ReplicaSummary"
          },
          "source": {
            "$ref": "#/components/schemas/ProviderMode"
          },
          "stale": {
            "type": "boolean",
            "description": "The answer could not be refreshed (Incus unreachable); the status is `unknown`."
          },
          "status": {
            "$ref": "#/components/schemas/DeploymentStatus"
          }
        }
      },
      "DeploymentStatus": {
        "type": "string",
        "enum": [
          "not-deployed",
          "starting",
          "running",
          "degraded",
          "stopping",
          "migrating",
          "updating",
          "stopped",
          "failed",
          "unknown"
        ]
      },
      "DesignInfo": {
        "type": "object",
        "required": [
          "status",
          "validationErrors",
          "hasUnpublishedChanges"
        ],
        "properties": {
          "draftVersion": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "hasUnpublishedChanges": {
            "type": "boolean",
            "description": "The draft has changes that no published version contains."
          },
          "publishedVersion": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "status": {
            "$ref": "#/components/schemas/DesignStatus"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "validationErrors": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "DesignStatus": {
        "type": "string",
        "enum": [
          "draft",
          "validated",
          "published"
        ]
      },
      "DesiredModule": {
        "type": "object",
        "description": "One module of the design, turned into the instances it should run as.",
        "required": [
          "module",
          "spec"
        ],
        "properties": {
          "availability": {
            "$ref": "#/components/schemas/Availability"
          },
          "dnsResolver": {
            "type": "boolean",
            "description": "This module answers service names for the application. Absent\nmeans it does not: a resolver is never added unless the design asks for one."
          },
          "guestOs": {
            "$ref": "#/components/schemas/GuestOs",
            "description": "The operating system inside (from the class): decides which sessions it offers."
          },
          "internet": {
            "$ref": "#/components/schemas/Internet",
            "description": "What it may reach outside the application (enforced with the connections)."
          },
          "module": {
            "type": "string",
            "description": "The module's stable id in the design (e.g. `nginx-01`)."
          },
          "readiness": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Readiness",
                "description": "A command that runs inside each instance and exits 0 when the application is ready\n(from the class); the port check alone cannot tell a hung application from a ready one."
              },
              {
                "type": "null"
              }
            ]
          },
          "replicas": {
            "type": "integer",
            "format": "int32",
            "description": "How many instances (1–9); more than one only for stateless modules.",
            "minimum": 0
          },
          "spec": {
            "$ref": "#/components/schemas/InstanceSpec",
            "description": "Image, kind and settings; the control plane sets the name, project and owner."
          }
        }
      },
      "DirectoryCheck": {
        "type": "object",
        "required": [
          "ok",
          "message"
        ],
        "properties": {
          "entry": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/CheckedEntry"
              },
              {
                "type": "null"
              }
            ]
          },
          "message": {
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          },
          "problem": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/DirectoryProblem",
                "description": "What went wrong, when it did."
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "DirectoryCheckRequest": {
        "type": "object",
        "description": "Settings to check (saved or not) and a test username and password, which are used for one\nbind and never stored or logged.",
        "required": [
          "settings",
          "username",
          "password"
        ],
        "properties": {
          "directory": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The saved directory these settings are for, if any: only its group mappings are shown."
          },
          "password": {
            "type": "string",
            "format": "password"
          },
          "settings": {
            "$ref": "#/components/schemas/DirectoryInput"
          },
          "username": {
            "type": "string"
          }
        }
      },
      "DirectoryInput": {
        "type": "object",
        "description": "The settings of a directory. Empty optional fields take the defaults shown.",
        "required": [
          "name",
          "url",
          "bindTemplate"
        ],
        "properties": {
          "baseDn": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where to search for the person's entry after the bind."
          },
          "bindTemplate": {
            "type": "string",
            "description": "The bind name with `{username}`: a DN (`uid={username},ou=people,dc=example,dc=org`) or\na principal name (`{username}@example.org`, which needs `baseDn` and `userFilter`)."
          },
          "caPem": {
            "type": [
              "string",
              "null"
            ],
            "description": "The certificate authority that signed the directory's certificate (PEM); empty: the\nsystem's trusted roots."
          },
          "emailAttribute": {
            "type": [
              "string",
              "null"
            ],
            "description": "Default `mail`."
          },
          "enabled": {
            "type": "boolean"
          },
          "groupAttribute": {
            "type": [
              "string",
              "null"
            ],
            "description": "An attribute of the person's entry that lists their groups, e.g. `memberOf`."
          },
          "groupBaseDn": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where to search for groups that name the person."
          },
          "groupFilter": {
            "type": [
              "string",
              "null"
            ],
            "description": "The group search, with `{dn}` and `{username}` (default `(member={dn})`)."
          },
          "groupNameAttribute": {
            "type": [
              "string",
              "null"
            ],
            "description": "The group attribute that holds the group's name (default `cn`)."
          },
          "idAttribute": {
            "type": [
              "string",
              "null"
            ],
            "description": "The entry's stable id (default `entryUUID`; `objectGUID` is read as hex)."
          },
          "name": {
            "type": "string",
            "description": "What the sign-in form calls it (1 to 60 characters)."
          },
          "nameAttribute": {
            "type": [
              "string",
              "null"
            ],
            "description": "Default `cn`."
          },
          "startTls": {
            "type": "boolean"
          },
          "url": {
            "type": "string",
            "description": "`ldaps://host[:port]`, or `ldap://host[:port]` with `startTls`. Plain LDAP is refused."
          },
          "userFilter": {
            "type": [
              "string",
              "null"
            ],
            "description": "Finds the person's entry under `baseDn`, with `{username}`, e.g.\n`(userPrincipalName={username}@example.org)`. Empty: the entry is the bind DN itself."
          },
          "usernameAttribute": {
            "type": [
              "string",
              "null"
            ],
            "description": "Default `uid`."
          }
        }
      },
      "DirectoryList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DirectoryView"
            }
          }
        }
      },
      "DirectoryOption": {
        "type": "object",
        "description": "A directory people can choose on the sign-in page.",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "DirectoryProblem": {
        "type": "string",
        "description": "Why talking to a directory failed, in words an administrator can act on.",
        "enum": [
          "unreachable",
          "timeout",
          "tls",
          "certificate-untrusted",
          "certificate-name-mismatch",
          "start-tls-refused",
          "bind-refused",
          "entry-not-found",
          "entry-ambiguous",
          "search-failed",
          "settings"
        ]
      },
      "DirectoryView": {
        "type": "object",
        "description": "A saved directory, with whether it answered a TLS connect check just now.",
        "required": [
          "id",
          "name",
          "url",
          "startTls",
          "bindTemplate",
          "idAttribute",
          "usernameAttribute",
          "emailAttribute",
          "nameAttribute",
          "groupNameAttribute",
          "enabled",
          "reachable",
          "updatedBy"
        ],
        "properties": {
          "baseDn": {
            "type": [
              "string",
              "null"
            ]
          },
          "bindTemplate": {
            "type": "string"
          },
          "caPem": {
            "type": [
              "string",
              "null"
            ]
          },
          "emailAttribute": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "groupAttribute": {
            "type": [
              "string",
              "null"
            ]
          },
          "groupBaseDn": {
            "type": [
              "string",
              "null"
            ]
          },
          "groupFilter": {
            "type": [
              "string",
              "null"
            ]
          },
          "groupNameAttribute": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "idAttribute": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "nameAttribute": {
            "type": "string"
          },
          "problem": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/DirectoryProblem"
              },
              {
                "type": "null"
              }
            ]
          },
          "reachable": {
            "type": "boolean",
            "description": "Whether a TLS connection (with certificate and host-name checks) worked just now;\nfalse for a directory that is turned off."
          },
          "startTls": {
            "type": "boolean"
          },
          "updatedBy": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "userFilter": {
            "type": [
              "string",
              "null"
            ]
          },
          "usernameAttribute": {
            "type": "string"
          }
        }
      },
      "DraftDto": {
        "type": "object",
        "required": [
          "version",
          "document",
          "validationErrors",
          "updatedBy",
          "updatedAt"
        ],
        "properties": {
          "document": {
            "type": "object",
            "description": "A Studio document (the application assembly format the Studio imports and exports)."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedBy": {
            "type": "string"
          },
          "validationErrors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "version": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "DrillInfo": {
        "type": "object",
        "description": "A restore drill's record (`apelora-restore-drill/1`).",
        "required": [
          "drilledAt",
          "backup",
          "passed",
          "reason",
          "durationSeconds"
        ],
        "properties": {
          "backup": {
            "type": "string",
            "description": "The backup file the drill restored."
          },
          "drilledAt": {
            "type": "string",
            "format": "date-time"
          },
          "durationSeconds": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "passed": {
            "type": "boolean"
          },
          "reason": {
            "type": "string"
          }
        }
      },
      "EffectivePermission": {
        "type": "object",
        "required": [
          "permission",
          "class",
          "description",
          "grants"
        ],
        "properties": {
          "class": {
            "$ref": "#/components/schemas/Class"
          },
          "description": {
            "type": "string"
          },
          "grants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Grant"
            },
            "description": "Where each part of this permission comes from."
          },
          "permission": {
            "type": "string"
          }
        }
      },
      "EffectiveSetting": {
        "type": "object",
        "required": [
          "name",
          "set",
          "isDefault",
          "source",
          "readBy",
          "description",
          "known"
        ],
        "properties": {
          "default": {
            "type": [
              "string",
              "null"
            ],
            "description": "What applies when it is not set; absent when the feature is then off."
          },
          "description": {
            "type": "string"
          },
          "hidden": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the value is not shown: `secret` (a secret or a key or certificate file),\n`looks like a credential`, `unknown setting`; absent when shown or not set."
          },
          "isDefault": {
            "type": "boolean",
            "description": "The default applies (not set, or set to the default)."
          },
          "known": {
            "type": "boolean",
            "description": "A setting this version reads; `false` for an `APELORA_*` variable it ignores (a typo?)."
          },
          "name": {
            "type": "string"
          },
          "readBy": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Which processes read it: `control-plane`, `worker`, `web-dev-server`."
          },
          "set": {
            "type": "boolean",
            "description": "Set in the environment (or saved in the Console)."
          },
          "source": {
            "type": "string",
            "description": "`environment`, `default`, `not set` or `console`."
          },
          "value": {
            "type": [
              "string",
              "null"
            ],
            "description": "The value in use, when it may be shown (the default when not set)."
          }
        }
      },
      "EffectiveSettings": {
        "type": "object",
        "required": [
          "items",
          "saved",
          "workers",
          "readAt"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EffectiveSetting"
            },
            "description": "Environment settings of this control plane, in name order, then unknown `APELORA_*`\nvariables."
          },
          "readAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339: when this control plane read its environment."
          },
          "saved": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EffectiveSetting"
            },
            "description": "Sign-in settings saved in the Console."
          },
          "workers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SettingsWorker"
            },
            "description": "Workers seen in the last day. They do not report their settings: the worker's values\nare those of its own environment, which Apelora cannot read."
          }
        }
      },
      "EmergencyAccess": {
        "type": "object",
        "required": [
          "userId",
          "role",
          "reason",
          "minutes"
        ],
        "properties": {
          "minutes": {
            "type": "integer",
            "format": "int64",
            "description": "5–240 minutes."
          },
          "reason": {
            "type": "string",
            "description": "Why; at least 10 characters. Recorded in the audit trail."
          },
          "role": {
            "type": "string",
            "description": "A predefined role key, e.g. `fabric-administrator`."
          },
          "userId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "EnvKind": {
        "type": "string",
        "description": "Kind of environment; policies such as \"production needs MFA\" refer to it.",
        "enum": [
          "production",
          "staging",
          "development",
          "other"
        ]
      },
      "EnvironmentDto": {
        "type": "object",
        "required": [
          "id",
          "projectId",
          "slug",
          "name",
          "kind",
          "incusProjectConfig",
          "incusProvisioned",
          "incusState",
          "incusDetail"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "incusDetail": {
            "type": "string",
            "description": "Why it is still pending, or what preparing it found."
          },
          "incusProject": {
            "type": [
              "string",
              "null"
            ],
            "description": "The restricted Incus project this environment deploys into."
          },
          "incusProjectConfig": {
            "type": "object",
            "description": "The restrictions and features of a project Apelora creates; an adopted\nproject keeps its own (see the Tenancy page for what Incus has).",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "incusProvisioned": {
            "type": "boolean",
            "description": "Apelora created or adopted the Incus project (`incusState` is not `pending`)."
          },
          "incusState": {
            "$ref": "#/components/schemas/TenancyIncusState"
          },
          "kind": {
            "$ref": "#/components/schemas/EnvKind"
          },
          "name": {
            "type": "string"
          },
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "EnvironmentList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnvironmentDto"
            }
          }
        }
      },
      "EnvironmentRef": {
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "kind"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "incusProject": {
            "type": [
              "string",
              "null"
            ]
          },
          "kind": {
            "$ref": "#/components/schemas/EnvKind"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "ErrorBody": {
        "type": "object",
        "description": "Error body for every non-2xx response.",
        "required": [
          "error"
        ],
        "properties": {
          "currentVersion": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "With `draft_conflict` only: the version someone else saved, to start again from."
          },
          "error": {
            "$ref": "#/components/schemas/ErrorDetail"
          }
        }
      },
      "ErrorDetail": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable machine-readable code, e.g. `incus_unreachable`, `unauthenticated`, `forbidden`."
          },
          "message": {
            "type": "string"
          }
        }
      },
      "EvacuationItem": {
        "type": "object",
        "description": "One instance on the member being evacuated.",
        "required": [
          "project",
          "instance",
          "status",
          "mode",
          "outcome",
          "impact"
        ],
        "properties": {
          "application": {
            "type": [
              "string",
              "null"
            ]
          },
          "impact": {
            "type": "string",
            "description": "What it means for the application while the member is evacuated."
          },
          "instance": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "description": "Effective `cluster.evacuate` mode (`auto` when unset)."
          },
          "module": {
            "type": [
              "string",
              "null"
            ]
          },
          "outcome": {
            "type": "string",
            "description": "What Incus will do with it."
          },
          "project": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "EvacuationPlan": {
        "type": "object",
        "required": [
          "member",
          "targets",
          "items",
          "blocked",
          "warnings"
        ],
        "properties": {
          "blocked": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Why evacuating now is refused; empty when it may proceed."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EvacuationItem"
            }
          },
          "member": {
            "type": "string"
          },
          "targets": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Members that can take instances (online, other than this one)."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Consequences to accept before proceeding."
          }
        }
      },
      "EvacuationPreview": {
        "type": "object",
        "required": [
          "source",
          "plan"
        ],
        "properties": {
          "plan": {
            "$ref": "#/components/schemas/EvacuationPlan"
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "FenceCondition": {
        "type": "string",
        "enum": [
          "waiting",
          "fenced"
        ]
      },
      "FenceConfirmation": {
        "type": "object",
        "description": "A person's confirmation that a failed server is powered off.",
        "required": [
          "confirm",
          "poweredOff"
        ],
        "properties": {
          "confirm": {
            "type": "string",
            "description": "The member's name again, typed by the person."
          },
          "poweredOff": {
            "type": "boolean",
            "description": "Must be `true`: the server is switched off (or cut off from the shared storage)."
          }
        }
      },
      "FenceEvidence": {
        "type": "object",
        "description": "The evidence a fencing decision rests on; recorded and audited with it.",
        "required": [
          "kind",
          "at",
          "summary"
        ],
        "properties": {
          "at": {
            "type": "integer",
            "format": "int64",
            "description": "When it was observed or confirmed (Unix seconds)."
          },
          "confirmedBy": {
            "type": [
              "string",
              "null"
            ],
            "description": "Who confirmed (confirmation)."
          },
          "generation": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "hostId": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "minimum": 0
          },
          "kind": {
            "$ref": "#/components/schemas/FenceKind"
          },
          "lockspace": {
            "type": [
              "string",
              "null"
            ]
          },
          "observedBy": {
            "type": [
              "string",
              "null"
            ],
            "description": "The member whose sanlock reported the lease (storage lease)."
          },
          "provider": {
            "type": [
              "string",
              "null"
            ],
            "description": "Which fence provider read the power state (power-off): `redfish`, `lima`."
          },
          "summary": {
            "type": "string"
          }
        }
      },
      "FenceKind": {
        "type": "string",
        "description": "How the failed member was fenced.",
        "enum": [
          "storage-lease",
          "confirmed",
          "power-off"
        ]
      },
      "FenceLeaseState": {
        "type": "string",
        "description": "How a remote host's lease looks to sanlock on the member that was asked.",
        "enum": [
          "free",
          "live",
          "fail",
          "dead",
          "unknown"
        ]
      },
      "FenceView": {
        "type": "object",
        "description": "A failed member's fencing state, with the reason and what a person can do.",
        "required": [
          "condition",
          "reason"
        ],
        "properties": {
          "condition": {
            "$ref": "#/components/schemas/FenceCondition"
          },
          "evidence": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/FenceEvidence"
              },
              {
                "type": "null"
              }
            ]
          },
          "leaseState": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/FenceLeaseState",
                "description": "The latest reading of the member's lease, when there is one."
              },
              {
                "type": "null"
              }
            ]
          },
          "nextStep": {
            "type": [
              "string",
              "null"
            ]
          },
          "observedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "observedBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "reason": {
            "type": "string"
          }
        }
      },
      "Grant": {
        "type": "object",
        "required": [
          "assignment",
          "role",
          "roleName",
          "scope",
          "emergency"
        ],
        "properties": {
          "assignment": {
            "type": "string",
            "format": "uuid"
          },
          "emergency": {
            "type": "boolean"
          },
          "role": {
            "$ref": "#/components/schemas/RoleRef"
          },
          "roleName": {
            "type": "string"
          },
          "scope": {
            "$ref": "#/components/schemas/Scope"
          },
          "viaGroup": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Set when the grant reaches the caller through a group."
          }
        }
      },
      "GroupDto": {
        "type": "object",
        "required": [
          "id",
          "name",
          "needsSource",
          "description"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "externalName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The group's name in its source's tokens (a directory group's full DN), when members come\nfrom there."
          },
          "externalSource": {
            "type": [
              "string",
              "null"
            ],
            "description": "Who may assert membership: an identity provider's issuer, or `directory:<id>`."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "needsSource": {
            "type": "boolean",
            "description": "Mapped before sources were recorded: it matches nobody until a platform administrator\nsets its source (`PUT /api/v1/identity/groups/{group}/external`)."
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "`null` = a platform group."
          }
        }
      },
      "GroupExternal": {
        "type": "object",
        "description": "The group outside Apelora a group mirrors.",
        "required": [
          "source",
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "The group's name in the source's tokens; for a directory, the group's full DN."
          },
          "source": {
            "type": "string",
            "description": "One of the `sources` the group list names."
          }
        }
      },
      "GroupList": {
        "type": "object",
        "required": [
          "items",
          "sources"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GroupDto"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GroupSource"
            },
            "description": "The sources a group can be mapped to."
          }
        }
      },
      "GroupSource": {
        "type": "object",
        "description": "A place whose group memberships Apelora accepts: an identity provider (its tokens' groups)\nor a directory (its groups' DNs).",
        "required": [
          "id",
          "kind",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "What a mapping records: the provider's issuer, or `directory:<id>`."
          },
          "kind": {
            "$ref": "#/components/schemas/GroupSourceKind"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "GroupSourceKind": {
        "type": "string",
        "description": "The kind of a source of external groups.",
        "enum": [
          "identity-provider",
          "directory"
        ]
      },
      "GrowVolume": {
        "type": "object",
        "required": [
          "sizeMib"
        ],
        "properties": {
          "sizeMib": {
            "type": "integer",
            "format": "int32",
            "description": "The new size in MiB; at least the current one (volumes only grow).",
            "minimum": 0
          }
        }
      },
      "GuestOs": {
        "type": "string",
        "description": "The operating system inside a module, from its catalog class (never guessed from names).",
        "enum": [
          "linux",
          "windows"
        ]
      },
      "Health": {
        "type": "object",
        "description": "The public health answer: coarse status and Apelora's version (shown at the foot of the\nsign-in page). Incus versions and error text are on the authenticated `GET /api/v1/system`.",
        "required": [
          "status",
          "service",
          "version",
          "apiVersion",
          "provider",
          "auth",
          "incus",
          "checkedAt"
        ],
        "properties": {
          "apiVersion": {
            "type": "string"
          },
          "auth": {
            "$ref": "#/components/schemas/AuthMode"
          },
          "checkedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When Incus was last asked (RFC 3339, UTC); answers are reused for up to 15 s."
          },
          "incus": {
            "$ref": "#/components/schemas/IncusSummary"
          },
          "provider": {
            "$ref": "#/components/schemas/ProviderMode"
          },
          "service": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "`ok`: the control plane answers."
          },
          "version": {
            "type": "string",
            "description": "Apelora's version."
          }
        }
      },
      "HealthCondition": {
        "type": "string",
        "description": "A component's or server's state, worst last.",
        "enum": [
          "healthy",
          "not-set-up",
          "unknown",
          "degraded",
          "down"
        ]
      },
      "HealthControlPlane": {
        "type": "object",
        "required": [
          "state",
          "version",
          "apiVersion",
          "startedAt",
          "uptimeSecs",
          "auth",
          "provider"
        ],
        "properties": {
          "apiVersion": {
            "type": "string"
          },
          "auth": {
            "$ref": "#/components/schemas/AuthMode"
          },
          "nextStep": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider": {
            "$ref": "#/components/schemas/ProviderMode",
            "description": "Where inventory comes from: a real Incus server or labelled mock data."
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "state": {
            "$ref": "#/components/schemas/HealthCondition"
          },
          "uptimeSecs": {
            "type": "integer",
            "format": "int64"
          },
          "version": {
            "type": "string"
          }
        }
      },
      "HealthDatabase": {
        "type": "object",
        "required": [
          "state",
          "expectedSchemaVersion"
        ],
        "properties": {
          "expectedSchemaVersion": {
            "type": "integer",
            "format": "int64",
            "description": "The newest migration this build carries."
          },
          "nextStep": {
            "type": [
              "string",
              "null"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "roundTripMs": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Round trip of `SELECT 1` in milliseconds."
          },
          "schemaVersion": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "The newest migration applied."
          },
          "state": {
            "$ref": "#/components/schemas/HealthCondition"
          }
        }
      },
      "HealthIdentityProvider": {
        "type": "object",
        "required": [
          "name",
          "source",
          "enabled",
          "reachable"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "reachable": {
            "type": "boolean",
            "description": "Its keys could be fetched at the last check (unreachable ones are retried every minute)."
          },
          "source": {
            "type": "string",
            "description": "`environment` (set by the control plane's environment) or `console` (saved in the Console)."
          }
        }
      },
      "HealthIdentityProviders": {
        "type": "object",
        "required": [
          "state",
          "items",
          "apiTokens"
        ],
        "properties": {
          "apiTokens": {
            "type": "boolean",
            "description": "Whether API tokens are accepted."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HealthIdentityProvider"
            }
          },
          "nextStep": {
            "type": [
              "string",
              "null"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "$ref": "#/components/schemas/HealthCondition"
          }
        }
      },
      "HealthIncus": {
        "type": "object",
        "required": [
          "state",
          "provider"
        ],
        "properties": {
          "apiVersion": {
            "type": [
              "string",
              "null"
            ]
          },
          "clustered": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "members": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/HealthMemberCounts",
                "description": "`null` when Incus could not be read or is not clustered."
              },
              {
                "type": "null"
              }
            ]
          },
          "nextStep": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider": {
            "$ref": "#/components/schemas/ProviderMode"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "roundTripMs": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Round trip of `GET /1.0` in milliseconds."
          },
          "serverVersion": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "$ref": "#/components/schemas/HealthCondition"
          }
        }
      },
      "HealthInventory": {
        "type": "object",
        "description": "Networks or storage pools: how many, and which are not created everywhere they should be.",
        "required": [
          "state",
          "problems"
        ],
        "properties": {
          "nextStep": {
            "type": [
              "string",
              "null"
            ]
          },
          "problems": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "One line per problem, e.g. `br0: Errored` or `local: missing on node-3`."
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "$ref": "#/components/schemas/HealthCondition"
          },
          "total": {
            "type": [
              "integer",
              "null"
            ],
            "description": "`null` when Incus could not be read.",
            "minimum": 0
          }
        }
      },
      "HealthJobQueue": {
        "type": "object",
        "required": [
          "state"
        ],
        "properties": {
          "counts": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/HealthQueueCounts",
                "description": "`null` when the database could not be read."
              },
              {
                "type": "null"
              }
            ]
          },
          "nextStep": {
            "type": [
              "string",
              "null"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "$ref": "#/components/schemas/HealthCondition"
          }
        }
      },
      "HealthMemberCounts": {
        "type": "object",
        "description": "Cluster members by Incus status.",
        "required": [
          "total",
          "online",
          "evacuated",
          "offline",
          "other"
        ],
        "properties": {
          "evacuated": {
            "type": "integer",
            "minimum": 0
          },
          "offline": {
            "type": "integer",
            "minimum": 0
          },
          "online": {
            "type": "integer",
            "minimum": 0
          },
          "other": {
            "type": "integer",
            "description": "Any other status (for example Blocked).",
            "minimum": 0
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "HealthPoolUsage": {
        "type": "object",
        "description": "One storage pool's space on one server.",
        "required": [
          "name",
          "usedBytes",
          "totalBytes"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "totalBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "usedBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          }
        }
      },
      "HealthQueueCounts": {
        "type": "object",
        "description": "Counts of the job queue.",
        "required": [
          "waiting",
          "retrying",
          "running",
          "stalled",
          "failedLastHour"
        ],
        "properties": {
          "failedLastHour": {
            "type": "integer",
            "format": "int64"
          },
          "oldestWaitingSecs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Age of the oldest job ready to run."
          },
          "retrying": {
            "type": "integer",
            "format": "int64",
            "description": "Waiting for a retry or a scheduled time."
          },
          "running": {
            "type": "integer",
            "format": "int64"
          },
          "stalled": {
            "type": "integer",
            "format": "int64",
            "description": "Running, but the worker's lease expired (the worker died or hangs); claimed again soon."
          },
          "waiting": {
            "type": "integer",
            "format": "int64",
            "description": "Ready to run, waiting for a worker."
          }
        }
      },
      "HealthReport": {
        "type": "object",
        "description": "One state per component of this installation, with the reason and next step when it is not\nhealthy.",
        "required": [
          "checkedAt",
          "overall",
          "controlPlane",
          "database",
          "workers",
          "jobQueue",
          "incus",
          "networks",
          "storagePools",
          "identityProviders"
        ],
        "properties": {
          "checkedAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339: when this report was made."
          },
          "controlPlane": {
            "$ref": "#/components/schemas/HealthControlPlane"
          },
          "database": {
            "$ref": "#/components/schemas/HealthDatabase"
          },
          "identityProviders": {
            "$ref": "#/components/schemas/HealthIdentityProviders"
          },
          "incus": {
            "$ref": "#/components/schemas/HealthIncus"
          },
          "jobQueue": {
            "$ref": "#/components/schemas/HealthJobQueue"
          },
          "networks": {
            "$ref": "#/components/schemas/HealthInventory"
          },
          "overall": {
            "$ref": "#/components/schemas/HealthCondition",
            "description": "The worst component state (`not-set-up` counts as healthy)."
          },
          "storagePools": {
            "$ref": "#/components/schemas/HealthInventory"
          },
          "workers": {
            "$ref": "#/components/schemas/HealthWorkers"
          }
        }
      },
      "HealthServer": {
        "type": "object",
        "description": "One server (\"minion\"): an Incus cluster member, or the standalone Incus server.",
        "required": [
          "name",
          "status",
          "message",
          "state",
          "roles",
          "architecture",
          "failureDomain",
          "held",
          "instances",
          "warnings"
        ],
        "properties": {
          "architecture": {
            "type": "string"
          },
          "failureDomain": {
            "type": "string"
          },
          "held": {
            "type": "boolean",
            "description": "Kept out of automatic placement (`scheduler.instance=manual`)."
          },
          "instances": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HealthServerInstance"
            }
          },
          "message": {
            "type": "string",
            "description": "Incus's message for the status."
          },
          "name": {
            "type": "string"
          },
          "resources": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/HealthServerResources",
                "description": "`null` when they could not be read (see `resourcesError`)."
              },
              {
                "type": "null"
              }
            ]
          },
          "resourcesError": {
            "type": [
              "string",
              "null"
            ]
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "state": {
            "$ref": "#/components/schemas/HealthCondition"
          },
          "status": {
            "type": "string",
            "description": "Incus status: Online, Evacuated, Offline, Blocked, …"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Warnings decided by the server (memory above 90 %, a pool above 85 %, CPU busy, …)."
          }
        }
      },
      "HealthServerInstance": {
        "type": "object",
        "required": [
          "name",
          "project",
          "kind",
          "status",
          "managed"
        ],
        "properties": {
          "kind": {
            "$ref": "#/components/schemas/InstanceKind"
          },
          "managed": {
            "type": "boolean",
            "description": "Created and owned by Apelora."
          },
          "name": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "HealthServerResources": {
        "type": "object",
        "description": "What Incus reports about one server's resources. Fields Incus did not report are `None`\n(or empty), never zero.",
        "required": [
          "loadAverages",
          "pools"
        ],
        "properties": {
          "cpuThreads": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "CPU threads (all sockets and cores).",
            "minimum": 0
          },
          "loadAverages": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            },
            "description": "1, 5 and 15-minute load averages (clustered servers only)."
          },
          "memory": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/HealthUsage"
              },
              {
                "type": "null"
              }
            ]
          },
          "pools": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HealthPoolUsage"
            }
          },
          "uptimeSecs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          }
        }
      },
      "HealthServers": {
        "type": "object",
        "required": [
          "source",
          "clustered",
          "items"
        ],
        "properties": {
          "clustered": {
            "type": "boolean"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HealthServer"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "HealthState": {
        "type": "string",
        "description": "The decided health of an instance.",
        "enum": [
          "unknown",
          "healthy",
          "unhealthy"
        ]
      },
      "HealthUsage": {
        "type": "object",
        "description": "Used of total for one resource, in bytes.",
        "required": [
          "usedBytes",
          "totalBytes"
        ],
        "properties": {
          "totalBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "usedBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          }
        }
      },
      "HealthWorker": {
        "type": "object",
        "required": [
          "id",
          "host",
          "version",
          "startedAt",
          "lastSeen",
          "secondsSinceSeen",
          "state"
        ],
        "properties": {
          "host": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "lastSeen": {
            "type": "string",
            "description": "RFC 3339: the last heartbeat (written every 15 s)."
          },
          "secondsSinceSeen": {
            "type": "integer",
            "format": "int64"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "state": {
            "$ref": "#/components/schemas/HealthWorkerState"
          },
          "version": {
            "type": "string"
          }
        }
      },
      "HealthWorkerState": {
        "type": "string",
        "description": "A worker's state from the age of its last heartbeat.",
        "enum": [
          "running",
          "stopped",
          "lost"
        ]
      },
      "HealthWorkers": {
        "type": "object",
        "required": [
          "state",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HealthWorker"
            },
            "description": "Workers seen in the last day, most recently seen first."
          },
          "nextStep": {
            "type": [
              "string",
              "null"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "$ref": "#/components/schemas/HealthCondition"
          }
        }
      },
      "IdentityProjectList": {
        "type": "object",
        "description": "Identity projects (`/api/v1/identity/projects`); not the Incus projects of\n`/api/v1/projects`, whose schema is `ProjectList`.",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectDto"
            }
          }
        }
      },
      "ImageMirrorsReport": {
        "type": "object",
        "required": [
          "mode",
          "mirrors",
          "servers",
          "checks",
          "overall"
        ],
        "properties": {
          "checks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Check"
            },
            "description": "The same checks Preflight shows."
          },
          "mirrors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MirrorStatus"
            },
            "description": "`APELORA_IMAGE_MIRRORS` as this control plane read it at start. The worker reads its own\nenvironment, which must say the same."
          },
          "mode": {
            "$ref": "#/components/schemas/ImageServerMode",
            "description": "`mirrors-only` when `APELORA_IMAGE_SERVERS=mirrors-only`."
          },
          "overall": {
            "$ref": "#/components/schemas/CheckStatus",
            "description": "The worst status among the checks."
          },
          "servers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImageServerUse"
            }
          }
        }
      },
      "ImageProtocol": {
        "type": "string",
        "description": "How Incus fetches an image.",
        "enum": [
          "simplestreams",
          "oci"
        ]
      },
      "ImageServerMode": {
        "type": "string",
        "description": "Whether every image server may be used, or only the mirrors.",
        "enum": [
          "any",
          "mirrors-only"
        ]
      },
      "ImageServerUse": {
        "type": "object",
        "description": "An image server the catalog's deployable classes use, and how this installation covers it.",
        "required": [
          "server",
          "protocol",
          "coverage",
          "images"
        ],
        "properties": {
          "coverage": {
            "$ref": "#/components/schemas/CoverageKind"
          },
          "images": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClassImage"
            }
          },
          "mirror": {
            "type": [
              "string",
              "null"
            ],
            "description": "The mirror that serves it, when mirrored."
          },
          "protocol": {
            "$ref": "#/components/schemas/ImageProtocol"
          },
          "server": {
            "type": "string"
          }
        }
      },
      "ImageSource": {
        "type": "object",
        "description": "Where an instance's root image comes from.",
        "required": [
          "protocol",
          "server",
          "alias"
        ],
        "properties": {
          "alias": {
            "type": "string",
            "description": "Alias such as `debian/13` or, for OCI, `repository:tag`. Pin an OCI image by digest:\n`repository@sha256:<64 hex digits>`."
          },
          "fingerprint": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pins a simplestreams image: the full SHA-256 fingerprint Incus gives it. The instance\nmust then be built from exactly this image."
          },
          "protocol": {
            "$ref": "#/components/schemas/ImageProtocol"
          },
          "server": {
            "type": "string",
            "description": "Image server URL, e.g. a simplestreams server or an OCI registry."
          }
        }
      },
      "IncusProjectPrepared": {
        "type": "object",
        "description": "The result of preparing an environment's Incus project.",
        "required": [
          "environmentId",
          "state",
          "detail",
          "findings"
        ],
        "properties": {
          "detail": {
            "type": "string"
          },
          "environmentId": {
            "type": "string",
            "format": "uuid"
          },
          "findings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenancyFinding"
            }
          },
          "incusProject": {
            "type": [
              "string",
              "null"
            ]
          },
          "limits": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/TenancyLimitOutcome",
                "description": "The quotas mirrored right after (absent when the project is not ready)."
              },
              {
                "type": "null"
              }
            ]
          },
          "state": {
            "$ref": "#/components/schemas/TenancyIncusState"
          }
        }
      },
      "IncusStatus": {
        "type": "object",
        "description": "What the control plane knows about its Incus connection.",
        "required": [
          "connected",
          "serverVersion"
        ],
        "properties": {
          "apiVersion": {
            "type": "string"
          },
          "clustered": {
            "type": "boolean"
          },
          "connected": {
            "type": "boolean",
            "description": "True only when talking to a real Incus server (never for mock data)."
          },
          "error": {
            "type": "string"
          },
          "serverVersion": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "IncusSummary": {
        "type": "object",
        "description": "Whether the control plane can reach Incus, and nothing else.",
        "required": [
          "connected"
        ],
        "properties": {
          "connected": {
            "type": "boolean",
            "description": "True only when a real Incus server answered (never for mock data)."
          }
        }
      },
      "Instance": {
        "type": "object",
        "description": "Observed state of one Incus instance.",
        "required": [
          "name",
          "project",
          "kind",
          "status",
          "location",
          "architecture",
          "description"
        ],
        "properties": {
          "architecture": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "evacuate": {
            "type": [
              "string",
              "null"
            ],
            "description": "What Incus does with it when its member is evacuated (`cluster.evacuate`, with\nprofiles applied); `None`: Incus's default, `auto`."
          },
          "kind": {
            "$ref": "#/components/schemas/InstanceKind"
          },
          "limits": {
            "type": "object",
            "description": "The resource limits set on the instance itself (`limits.cpu`, `limits.cpu.allowance`,\n`limits.memory`), as Incus reports them; no other keys.",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "location": {
            "type": "string"
          },
          "managed": {
            "type": "boolean",
            "description": "Carries Apelora's ownership marker: only these can be stopped or deleted through Apelora."
          },
          "name": {
            "type": "string"
          },
          "owner": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Owner",
                "description": "The application and module this instance was deployed for (Apelora's labels)."
              },
              {
                "type": "null"
              }
            ]
          },
          "project": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "unreachable": {
            "type": "boolean",
            "description": "Incus cannot report its configuration because its member is unreachable, so its\nlabels (and `managed`, `owner`) are unknown, not absent."
          }
        }
      },
      "InstanceAccess": {
        "type": "object",
        "required": [
          "instance",
          "module",
          "guestOs",
          "status",
          "kinds"
        ],
        "properties": {
          "guestOs": {
            "$ref": "#/components/schemas/GuestOs"
          },
          "instance": {
            "type": "string"
          },
          "kinds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KindAccess"
            }
          },
          "module": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "InstanceAction": {
        "type": "string",
        "description": "A state change Apelora can request for one of its instances.",
        "enum": [
          "start",
          "stop",
          "restart"
        ]
      },
      "InstanceDetail": {
        "type": "object",
        "required": [
          "instance",
          "status",
          "location",
          "unhealthy"
        ],
        "properties": {
          "instance": {
            "type": "string"
          },
          "location": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "unhealthy": {
            "type": "boolean"
          }
        }
      },
      "InstanceHealth": {
        "type": "object",
        "required": [
          "health",
          "since",
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string",
            "description": "What the decision rests on, e.g. `port check failing`."
          },
          "health": {
            "$ref": "#/components/schemas/HealthState"
          },
          "restartedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "RFC 3339: when the worker last restarted it for failing its check."
          },
          "since": {
            "type": "string",
            "description": "RFC 3339: since when it has had this health."
          }
        }
      },
      "InstanceKind": {
        "type": "string",
        "description": "Kind of Incus instance as reported by the cluster.",
        "enum": [
          "container",
          "virtual-machine",
          "unknown"
        ]
      },
      "InstanceList": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Instance"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "InstanceLogList": {
        "type": "object",
        "description": "The instance's log files.",
        "required": [
          "source",
          "files"
        ],
        "properties": {
          "files": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "File names as Incus lists them (e.g. `lxc.log`, `qemu.log`)."
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "InstanceLogText": {
        "type": "object",
        "description": "The end of one log.",
        "required": [
          "source",
          "file",
          "tailKib",
          "log"
        ],
        "properties": {
          "file": {
            "type": "string",
            "description": "The file name, or `console` for the console log."
          },
          "log": {
            "$ref": "#/components/schemas/LogTail"
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          },
          "tailKib": {
            "type": "integer",
            "format": "int32",
            "description": "How much of the end was asked for, in KiB.",
            "minimum": 0
          }
        }
      },
      "InstancePage": {
        "type": "object",
        "description": "One instance as Incus reports it, with the application it belongs to and its recent jobs.",
        "required": [
          "source",
          "instance",
          "jobs",
          "actions"
        ],
        "properties": {
          "actions": {
            "$ref": "#/components/schemas/InstancePageActions"
          },
          "application": {
            "type": [
              "string",
              "null"
            ],
            "description": "The application it belongs to (its Apelora labels)."
          },
          "instance": {
            "$ref": "#/components/schemas/InstanceView"
          },
          "jobs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Job"
            },
            "description": "The latest jobs for it, newest first (at most 10)."
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "InstancePageActions": {
        "type": "object",
        "description": "What the caller may do with the instance, each with the reason when not.",
        "required": [
          "start",
          "stop",
          "restart",
          "move",
          "delete",
          "logs"
        ],
        "properties": {
          "delete": {
            "$ref": "#/components/schemas/ActionState"
          },
          "logs": {
            "$ref": "#/components/schemas/ActionState"
          },
          "move": {
            "$ref": "#/components/schemas/ActionState"
          },
          "restart": {
            "$ref": "#/components/schemas/ActionState"
          },
          "start": {
            "$ref": "#/components/schemas/ActionState"
          },
          "stop": {
            "$ref": "#/components/schemas/ActionState"
          }
        }
      },
      "InstanceSpec": {
        "type": "object",
        "description": "An instance Apelora should create. Apelora's ownership marker is added on creation.",
        "required": [
          "project",
          "name",
          "kind",
          "source"
        ],
        "properties": {
          "architectures": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Architectures the image is known to run on, as Incus names them (`x86_64`, `aarch64`, …);\nempty allows any.\nChecked against the cluster before creating and against the instance Incus created."
          },
          "config": {
            "type": "object",
            "description": "Extra instance config; keys under `user.apelora.` are reserved.",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "kind": {
            "$ref": "#/components/schemas/InstanceKind",
            "description": "`container` (system or OCI) or `virtual-machine`."
          },
          "name": {
            "type": "string"
          },
          "network": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/NetworkAttachment",
                "description": "Set by the control plane when the application's connections are enforced: the NIC\njoins the application's network with its own ACL (unmatched traffic rejected)."
              },
              {
                "type": "null"
              }
            ]
          },
          "owner": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Owner",
                "description": "Set by the control plane when the instance is part of an application deployment."
              },
              {
                "type": "null"
              }
            ]
          },
          "profiles": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Profiles to apply, in order; empty applies the project's `default` profile."
          },
          "project": {
            "type": "string"
          },
          "rootPool": {
            "type": [
              "string",
              "null"
            ],
            "description": "The pool of the root disk when it is not the one the project's profile gives: the shared\npool for a module that restarts on another member after a failure. Set by the\ncontrol plane from the module's volume classes, never by a caller."
          },
          "source": {
            "$ref": "#/components/schemas/ImageSource"
          },
          "start": {
            "type": "boolean",
            "description": "Start the instance once created."
          },
          "volumes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VolumeMount"
            },
            "description": "Persistent volumes, each created for this instance on the member it runs on."
          }
        }
      },
      "InstanceView": {
        "type": "object",
        "description": "An instance in detail (`/1.0/instances/{name}`, its `state` and its `snapshots`).",
        "required": [
          "name",
          "project",
          "kind",
          "status",
          "location",
          "architecture",
          "description",
          "managed",
          "profiles",
          "image",
          "limits",
          "addresses",
          "disks",
          "snapshots"
        ],
        "properties": {
          "addresses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InstanceViewAddress"
            }
          },
          "architecture": {
            "type": "string"
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "RFC 3339, as Incus reports them."
          },
          "description": {
            "type": "string"
          },
          "disks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InstanceViewDisk"
            }
          },
          "image": {
            "$ref": "#/components/schemas/InstanceViewImage"
          },
          "kind": {
            "$ref": "#/components/schemas/InstanceKind"
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "limits": {
            "$ref": "#/components/schemas/InstanceViewLimits"
          },
          "location": {
            "type": "string",
            "description": "The member it runs on; empty on a standalone server."
          },
          "managed": {
            "type": "boolean",
            "description": "Carries Apelora's ownership marker."
          },
          "name": {
            "type": "string"
          },
          "owner": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Owner",
                "description": "The application and module it was deployed for."
              },
              {
                "type": "null"
              }
            ]
          },
          "profiles": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "project": {
            "type": "string"
          },
          "snapshots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InstanceViewSnapshot"
            }
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the running instance started (`instance_state_started_at`)."
          },
          "status": {
            "type": "string",
            "description": "`Running`, `Stopped`, `Frozen`, `Error`, …"
          },
          "usage": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/InstanceViewUsage",
                "description": "`None` while stopped (Incus reports no usage then)."
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "InstanceViewAddress": {
        "type": "object",
        "description": "One address on one interface, as the instance reports it.",
        "required": [
          "interface",
          "family",
          "address",
          "netmask",
          "scope"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "family": {
            "type": "string",
            "description": "`inet` or `inet6`."
          },
          "interface": {
            "type": "string"
          },
          "netmask": {
            "type": "string"
          },
          "scope": {
            "type": "string",
            "description": "`global`, `link` or `local`."
          }
        }
      },
      "InstanceViewDisk": {
        "type": "object",
        "description": "A disk device (expanded devices: profiles applied).",
        "required": [
          "device"
        ],
        "properties": {
          "device": {
            "type": "string"
          },
          "path": {
            "type": [
              "string",
              "null"
            ],
            "description": "Mount path in the instance; `/` for the root disk; `None` for a block device."
          },
          "pool": {
            "type": [
              "string",
              "null"
            ]
          },
          "size": {
            "type": [
              "string",
              "null"
            ]
          },
          "volume": {
            "type": [
              "string",
              "null"
            ],
            "description": "The custom volume, for disks backed by one."
          }
        }
      },
      "InstanceViewImage": {
        "type": "object",
        "description": "The image it was built from (`image.*` and `volatile.base_image` config).",
        "properties": {
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "fingerprint": {
            "type": [
              "string",
              "null"
            ]
          },
          "os": {
            "type": [
              "string",
              "null"
            ]
          },
          "release": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "InstanceViewLimits": {
        "type": "object",
        "description": "Limits from the expanded configuration (profiles applied); `None`: no limit set.",
        "properties": {
          "cpu": {
            "type": [
              "string",
              "null"
            ],
            "description": "`limits.cpu` as written (a count or a set of CPUs)."
          },
          "memory": {
            "type": [
              "string",
              "null"
            ],
            "description": "`limits.memory` as written (e.g. `2GiB`, `50%`)."
          },
          "rootDisk": {
            "type": [
              "string",
              "null"
            ],
            "description": "`size` of the root disk device as written."
          }
        }
      },
      "InstanceViewSnapshot": {
        "type": "object",
        "required": [
          "name",
          "stateful"
        ],
        "properties": {
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "stateful": {
            "type": "boolean",
            "description": "Includes the running state (memory)."
          }
        }
      },
      "InstanceViewUsage": {
        "type": "object",
        "description": "Use reported by Incus for a running instance.",
        "properties": {
          "cpuNs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "CPU time used since start, in nanoseconds."
          },
          "memoryBytes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "memoryPeakBytes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "memoryTotalBytes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Memory available to it, when Incus reports it (`instances_state_total`)."
          },
          "processes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "rootDiskBytes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Root disk use in bytes."
          }
        }
      },
      "Internet": {
        "type": "string",
        "description": "What a module may reach outside the application (the internet, through the uplink).\nInside the application only connections count, whatever this says.",
        "enum": [
          "none",
          "web",
          "any"
        ]
      },
      "Job": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "status",
          "attempts",
          "maxAttempts",
          "incusOperations",
          "request",
          "createdAt",
          "updatedAt",
          "actions"
        ],
        "properties": {
          "actions": {
            "$ref": "#/components/schemas/JobActions",
            "description": "What the caller may do with it, each with the reason when not."
          },
          "attempts": {
            "type": "integer",
            "format": "int32"
          },
          "cancelRequestedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "RFC 3339; set once someone asked to cancel it."
          },
          "cancelRequestedBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "incusOperation": {
            "type": [
              "string",
              "null"
            ],
            "description": "The Incus operation the current attempt is waiting on, if any."
          },
          "incusOperations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Every Incus operation the job started, oldest first (kept after they finish)."
          },
          "kind": {
            "type": "string",
            "description": "`instance.create`, `instance.start`, `instance.stop`, `instance.restart`,\n`instance.delete`, `instance.rebuild`, `instance.resize`, `instance.move`,\n`instance.recover`, `volume.backup`, `volume.restore`, `network.sync`, `network.resync` or\n`application.operation`."
          },
          "lastError": {
            "type": [
              "string",
              "null"
            ]
          },
          "maxAttempts": {
            "type": "integer",
            "format": "int32"
          },
          "queuedBy": {
            "type": [
              "string",
              "null"
            ],
            "description": "Who asked for it (`user:…`, `service:…`, `token:…`); absent for jobs the supervisor or\nthe scheduler queued, and for jobs queued before this was recorded."
          },
          "request": {
            "type": "object",
            "description": "What the job was asked to do; its fields depend on `kind` (an instance specification\nfor `instance.create`, the instance's project and name for `instance.start`, …)."
          },
          "requestId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The `x-request-id` of the API request that queued the job; absent for jobs the\nsupervisor or the scheduler queued. The request's audit rows carry it as `requestId`."
          },
          "retriedBy": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The job that retries this one."
          },
          "retryOf": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The failed job this one retries."
          },
          "status": {
            "type": "string",
            "description": "`pending`, `running`, `succeeded`, `failed` or `cancelled`."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          }
        }
      },
      "JobAccepted": {
        "type": "object",
        "required": [
          "jobId",
          "created"
        ],
        "properties": {
          "created": {
            "type": "boolean",
            "description": "False when an earlier request with the same idempotency key already created the job."
          },
          "jobId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "JobActions": {
        "type": "object",
        "description": "What the caller may do with a job.",
        "required": [
          "retry",
          "cancel"
        ],
        "properties": {
          "cancel": {
            "$ref": "#/components/schemas/ActionState"
          },
          "retry": {
            "$ref": "#/components/schemas/ActionState"
          }
        }
      },
      "JobAttempt": {
        "type": "object",
        "description": "One attempt of a job.",
        "required": [
          "attempt",
          "worker",
          "startedAt",
          "incusOperations"
        ],
        "properties": {
          "attempt": {
            "type": "integer",
            "format": "int32"
          },
          "endedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "incusOperations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Incus operations this attempt started, oldest first."
          },
          "outcome": {
            "type": [
              "string",
              "null"
            ],
            "description": "`succeeded`, `failed`, `rejected`, `waiting`, `cancelled` or `lost` (its worker stopped\nrenewing the lease and another worker took the job over); absent while it runs."
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "worker": {
            "type": "string",
            "description": "The worker that ran it."
          }
        }
      },
      "JobCancellation": {
        "type": "object",
        "description": "The answer to a cancellation request.",
        "required": [
          "outcome",
          "job"
        ],
        "properties": {
          "job": {
            "$ref": "#/components/schemas/Job"
          },
          "outcome": {
            "type": "string",
            "description": "`cancelled` (it had not started: done) or `requested` (the worker stops at the next\nsafe point)."
          }
        }
      },
      "JobDetail": {
        "type": "object",
        "description": "A job with everything known about it.",
        "required": [
          "job",
          "target",
          "attempts",
          "linked",
          "safePoints"
        ],
        "properties": {
          "application": {
            "type": [
              "string",
              "null"
            ],
            "description": "The application it belongs to, if any."
          },
          "attempts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JobAttempt"
            }
          },
          "finishedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "job": {
            "$ref": "#/components/schemas/Job"
          },
          "linked": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LinkedJob"
            }
          },
          "safePoints": {
            "type": "string",
            "description": "Where a cancelled job of this kind stops."
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "RFC 3339: when the first attempt started, and when it reached a final status."
          },
          "target": {
            "type": "string",
            "description": "`project/name` or the application."
          }
        }
      },
      "JobList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Job"
            }
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass this as `after` for the next, older page; absent on the last page."
          }
        }
      },
      "JoinTokenCreated": {
        "type": "object",
        "required": [
          "memberName",
          "expiresAt",
          "token",
          "warnings"
        ],
        "properties": {
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339, as Incus reports it."
          },
          "memberName": {
            "type": "string"
          },
          "token": {
            "type": "string",
            "description": "Single-use secret for `incus admin init` on the new server. Shown only in this response."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "E.g. that the token lives longer than recommended."
          }
        }
      },
      "JoinTokenList": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PendingJoin"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "KindAccess": {
        "type": "object",
        "description": "What a person may open on one instance, with the reason when not.",
        "required": [
          "kind",
          "allowed",
          "approvalRequired"
        ],
        "properties": {
          "allowed": {
            "type": "boolean"
          },
          "approvalRequired": {
            "type": "boolean",
            "description": "Another person must approve first (production). The request goes through `/approvals`."
          },
          "kind": {
            "$ref": "#/components/schemas/SessionKind"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it is not available (permission, state, set-up). Absent when allowed."
          }
        }
      },
      "Level": {
        "type": "string",
        "description": "How wide a scope is. Lower is wider. `Pool` is a separate branch under the platform.",
        "enum": [
          "platform",
          "organization",
          "project",
          "application",
          "pool"
        ]
      },
      "LimitChange": {
        "type": "object",
        "description": "One limit that changes.",
        "required": [
          "key"
        ],
        "properties": {
          "from": {
            "type": [
              "string",
              "null"
            ],
            "description": "The value now; absent when no limit is set."
          },
          "key": {
            "type": "string"
          },
          "to": {
            "type": [
              "string",
              "null"
            ],
            "description": "The value after; absent when the limit is removed."
          }
        }
      },
      "LinkedJob": {
        "type": "object",
        "description": "A job linked to the one shown.",
        "required": [
          "id",
          "kind",
          "status",
          "relation",
          "target",
          "createdAt"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string"
          },
          "relation": {
            "type": "string",
            "description": "`retry-of` (the failed job this one repeats), `retried-by`, or `same-request` (queued\nby the same API request, e.g. an application operation's instance jobs)."
          },
          "status": {
            "type": "string"
          },
          "target": {
            "type": "string",
            "description": "`project/name` or the application."
          }
        }
      },
      "LocalAccountCreated": {
        "type": "object",
        "required": [
          "user",
          "setupToken",
          "setupExpiresAt"
        ],
        "properties": {
          "setupExpiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "setupToken": {
            "type": "string",
            "description": "The one-time setup token; put it in the link `#/set-password?token=…`. Shown only here."
          },
          "user": {
            "$ref": "#/components/schemas/UserDto"
          }
        }
      },
      "LocalAccountInput": {
        "type": "object",
        "required": [
          "username"
        ],
        "properties": {
          "displayName": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "username": {
            "type": "string",
            "description": "2 to 64 of `a-z 0-9 . _ -` (stored lowercase)."
          }
        }
      },
      "LocalAccountSetting": {
        "type": "object",
        "required": [
          "enabled",
          "ready",
          "pending"
        ],
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Whether people may sign in with a local account (default off)."
          },
          "pending": {
            "type": "integer",
            "format": "int64",
            "description": "Local accounts whose setup link has not been used yet."
          },
          "ready": {
            "type": "integer",
            "format": "int64",
            "description": "Local accounts with a password that are not disabled: they can sign in."
          }
        }
      },
      "LocalAccountSetupLink": {
        "type": "object",
        "required": [
          "setupToken",
          "setupExpiresAt"
        ],
        "properties": {
          "setupExpiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "setupToken": {
            "type": "string",
            "description": "The one-time setup token. Shown only here."
          }
        }
      },
      "LocalAccountsRequest": {
        "type": "object",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "LogTail": {
        "type": "object",
        "description": "The end of a log as read: at most the requested number of bytes from its end.",
        "required": [
          "content",
          "size",
          "truncated"
        ],
        "properties": {
          "content": {
            "type": "string",
            "description": "The text (invalid UTF-8 replaced); starts at a line boundary when it was cut."
          },
          "size": {
            "type": "integer",
            "format": "int64",
            "description": "The whole log's size in bytes as received.",
            "minimum": 0
          },
          "truncated": {
            "type": "boolean",
            "description": "Only the end is shown."
          }
        }
      },
      "MaasAccepted": {
        "type": "object",
        "required": [
          "systemId",
          "hostname",
          "action"
        ],
        "properties": {
          "action": {
            "type": "string"
          },
          "hostname": {
            "type": "string"
          },
          "systemId": {
            "type": "string"
          }
        }
      },
      "MaasConfirm": {
        "type": "object",
        "required": [
          "confirm"
        ],
        "properties": {
          "confirm": {
            "type": "string",
            "description": "The machine's hostname, typed again."
          }
        }
      },
      "MaasDeploy": {
        "type": "object",
        "required": [
          "confirm",
          "distroSeries",
          "userData"
        ],
        "properties": {
          "confirm": {
            "type": "string"
          },
          "distroSeries": {
            "type": "string",
            "description": "MAAS's series name, such as `noble`."
          },
          "userData": {
            "type": "string",
            "description": "Cloud-init. Sent to MAAS and not stored. A join token in it is not kept."
          }
        }
      },
      "MaasMachineView": {
        "type": "object",
        "required": [
          "systemId",
          "hostname",
          "status",
          "testingStatus",
          "powerState",
          "powerType",
          "architecture",
          "cpuCount",
          "memoryMib",
          "os",
          "addresses",
          "zone",
          "pool"
        ],
        "properties": {
          "addresses": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "architecture": {
            "type": "string"
          },
          "cpuCount": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "hardwareUuid": {
            "type": [
              "string",
              "null"
            ],
            "description": "The server's hardware UUID (needed for the BMC fence mapping); absent until commissioned."
          },
          "hostname": {
            "type": "string"
          },
          "memberStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "The Incus member status of that machine, once it has joined."
          },
          "memoryMib": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "os": {
            "type": "string"
          },
          "pool": {
            "type": "string"
          },
          "powerState": {
            "type": "string",
            "description": "`on`, `off`, `unknown` or `error`, as MAAS last read it from the BMC."
          },
          "powerType": {
            "type": "string",
            "description": "How MAAS switches it: `ipmi`, `redfish`, `manual`, `virsh`…"
          },
          "registeredAs": {
            "type": [
              "string",
              "null"
            ],
            "description": "The Apelora machine registered for it, when there is one."
          },
          "status": {
            "type": "string",
            "description": "`New`, `Commissioning`, `Ready`, `Allocated`, `Deploying`, `Deployed`, `Failed …`."
          },
          "systemId": {
            "type": "string",
            "description": "MAAS's identifier; give it when registering the machine."
          },
          "testingStatus": {
            "type": "string",
            "description": "The last hardware test run (burn-in): `Passed`, `Failed`, `Running`, `Pending`, `None`, …"
          },
          "zone": {
            "type": "string"
          }
        }
      },
      "MaasMachines": {
        "type": "object",
        "required": [
          "source",
          "configured",
          "items"
        ],
        "properties": {
          "configured": {
            "type": "boolean",
            "description": "`false` when `APELORA_MAAS_URL` is not set: nothing to list, and what to do about it."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MaasMachineView"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "MaasRelease": {
        "type": "object",
        "required": [
          "confirm"
        ],
        "properties": {
          "confirm": {
            "type": "string"
          },
          "eraseDisks": {
            "type": "boolean",
            "description": "Wipe the installed system. Off unless the caller sets it. A secure wipe is not offered."
          }
        }
      },
      "MaasTest": {
        "type": "object",
        "required": [
          "confirm"
        ],
        "properties": {
          "confirm": {
            "type": "string"
          },
          "scripts": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "MAAS test script or tag names (up to 16). Empty runs MAAS's default tests."
          }
        }
      },
      "Machine": {
        "type": "object",
        "required": [
          "name",
          "provider",
          "capabilities",
          "description",
          "state",
          "nextStep",
          "warnings",
          "registeredBy",
          "registeredAt"
        ],
        "properties": {
          "admittedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "admittedBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "approvalExpiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the approval's join token stops working, as Incus reported it."
          },
          "approvedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "approvedBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "architecture": {
            "type": [
              "string",
              "null"
            ]
          },
          "capabilities": {
            "$ref": "#/components/schemas/Capabilities",
            "description": "What the provider can do without someone at the server."
          },
          "description": {
            "type": "string"
          },
          "memberStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "The cluster member's status (`Online`, `Offline`, `Evacuated`…) once it has joined."
          },
          "name": {
            "type": "string"
          },
          "nextStep": {
            "type": "string",
            "description": "What the administrator does next."
          },
          "provider": {
            "$ref": "#/components/schemas/ProvisionerKind"
          },
          "providerRef": {
            "type": [
              "string",
              "null"
            ],
            "description": "The provisioner's own identifier (a MAAS system id); absent for manual machines."
          },
          "registeredAt": {
            "type": "string",
            "format": "date-time"
          },
          "registeredBy": {
            "type": "string"
          },
          "state": {
            "$ref": "#/components/schemas/MachineState"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "MachineApproved": {
        "type": "object",
        "required": [
          "name",
          "expiresAt",
          "token",
          "enrolCommand",
          "warnings"
        ],
        "properties": {
          "enrolCommand": {
            "type": "string",
            "description": "What to run on the server; it asks for the token without echoing it."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339, as Incus reports it."
          },
          "name": {
            "type": "string"
          },
          "token": {
            "type": "string",
            "description": "Single-use join token for the enrolment script. Shown only in this response."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "MachineList": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Machine"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "MachineState": {
        "type": "string",
        "description": "Where a machine is in enrolment. Derived from the record and from Incus, never stored.",
        "enum": [
          "registered",
          "approved",
          "approval-expired",
          "held",
          "eligible",
          "left"
        ]
      },
      "MemberStateStarted": {
        "type": "object",
        "required": [
          "member",
          "operation",
          "drain"
        ],
        "properties": {
          "drain": {
            "type": "string",
            "description": "What was done first so no request goes to a replica Incus is about to move: the\nreplicas taken out of their service addresses, and whether that finished in time."
          },
          "member": {
            "type": "string"
          },
          "operation": {
            "type": "string",
            "description": "Incus operation carrying out the evacuation or restore."
          }
        }
      },
      "MetricsEndpoint": {
        "type": "object",
        "description": "One place a collector scrapes.",
        "required": [
          "component",
          "path",
          "authentication"
        ],
        "properties": {
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "`host:port` for listeners; absent for the API's own address (the one the caller used)."
          },
          "authentication": {
            "type": "string",
            "description": "`bearer` (a token with `fabric.metrics.read`) or `none` (keep it off public networks)."
          },
          "component": {
            "type": "string",
            "description": "`control-plane`, `control-plane-listener` (separate, unauthenticated) or `worker`."
          },
          "path": {
            "type": "string"
          }
        }
      },
      "MigrationItemDto": {
        "type": "object",
        "required": [
          "module",
          "instance",
          "from",
          "alreadyThere",
          "live",
          "stops",
          "copyMib",
          "blocked",
          "notes"
        ],
        "properties": {
          "alreadyThere": {
            "type": "boolean",
            "description": "Already on the target: nothing to move."
          },
          "blocked": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Why this instance cannot move; empty when it can."
          },
          "copyMib": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "from": {
            "type": "string"
          },
          "instance": {
            "type": "string"
          },
          "live": {
            "type": "boolean",
            "description": "Moves while running."
          },
          "module": {
            "type": "string"
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "stops": {
            "type": "boolean",
            "description": "Stops for the move and starts again on the target."
          }
        }
      },
      "MigrationPreview": {
        "type": "object",
        "required": [
          "source",
          "target",
          "items",
          "possible",
          "stops"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MigrationItemDto"
            }
          },
          "possible": {
            "type": "boolean",
            "description": "Whether a migration to the target can start (nothing blocks it and something moves)."
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          },
          "stops": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The instances that stop while they move: starting the migration then needs a confirmation."
          },
          "target": {
            "type": "string"
          }
        }
      },
      "MirrorStatus": {
        "type": "object",
        "description": "One configured mirror and whether it answered.",
        "required": [
          "upstream",
          "mirror",
          "probe"
        ],
        "properties": {
          "checkedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "RFC 3339: when the probe ran (results are reused for a minute)."
          },
          "mirror": {
            "type": "string"
          },
          "probe": {
            "$ref": "#/components/schemas/Probe"
          },
          "upstream": {
            "type": "string",
            "description": "The upstream image server it stands in for."
          }
        }
      },
      "ModuleDetail": {
        "type": "object",
        "required": [
          "module",
          "replicas",
          "availability",
          "instances"
        ],
        "properties": {
          "availability": {
            "$ref": "#/components/schemas/Availability"
          },
          "instances": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InstanceDetail"
            }
          },
          "module": {
            "type": "string"
          },
          "replicas": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "ModuleStatus": {
        "type": "object",
        "required": [
          "module",
          "instance",
          "project",
          "status",
          "location"
        ],
        "properties": {
          "health": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/InstanceHealth",
                "description": "What the worker decided from the instance's port check, with hysteresis; absent for\ninstances that are not checked (no service address, not running, or no database)."
              },
              {
                "type": "null"
              }
            ]
          },
          "instance": {
            "type": "string"
          },
          "location": {
            "type": "string"
          },
          "module": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Incus status, e.g. `Running`."
          }
        }
      },
      "MonitoringInfo": {
        "type": "object",
        "description": "How monitoring is set up, for the Console's Monitoring panel.",
        "required": [
          "region",
          "site",
          "sector",
          "provider",
          "mayScrape",
          "permission",
          "role",
          "endpoints",
          "formats",
          "incusMetricsPath"
        ],
        "properties": {
          "endpoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricsEndpoint"
            }
          },
          "formats": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Media types `GET /metrics` can answer with."
          },
          "incusMetricsPath": {
            "type": "string",
            "description": "Incus's own metrics path on every member, scraped directly with a metrics certificate."
          },
          "mayScrape": {
            "type": "boolean",
            "description": "The caller holds `fabric.metrics.read` and could scrape `GET /metrics` with its credential."
          },
          "permission": {
            "type": "string",
            "description": "The permission a collector needs (`fabric.metrics.read`)."
          },
          "provider": {
            "$ref": "#/components/schemas/ProviderMode"
          },
          "region": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "description": "The built-in role that holds only that permission."
          },
          "sector": {
            "type": "string"
          },
          "site": {
            "type": "string"
          }
        }
      },
      "MovePlan": {
        "type": "object",
        "description": "What the move does, decided before anything changes.",
        "required": [
          "instance",
          "from",
          "to",
          "live",
          "stops",
          "volumes",
          "copyMib",
          "blocked",
          "notes"
        ],
        "properties": {
          "blocked": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Why the move is refused; empty when it may proceed."
          },
          "copyMib": {
            "type": "integer",
            "format": "int64",
            "description": "How much data is copied while it is stopped, in MiB.",
            "minimum": 0
          },
          "from": {
            "type": "string"
          },
          "instance": {
            "type": "string"
          },
          "live": {
            "type": "boolean",
            "description": "Moves while running."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What to expect, in sentences."
          },
          "stops": {
            "type": "boolean",
            "description": "Stops for the move (and starts again on the new member if it was running)."
          },
          "to": {
            "type": "string"
          },
          "volumes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Volumes copied to the new member, then deleted on the old one once it runs there."
          }
        }
      },
      "MovePreview": {
        "type": "object",
        "required": [
          "source",
          "plan"
        ],
        "properties": {
          "plan": {
            "$ref": "#/components/schemas/MovePlan"
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "MoveRequest": {
        "type": "object",
        "required": [
          "target",
          "confirm"
        ],
        "properties": {
          "allowStop": {
            "type": "boolean"
          },
          "confirm": {
            "type": "string",
            "description": "The instance's name again, typed by the person moving it."
          },
          "target": {
            "type": "string"
          }
        }
      },
      "NetApplication": {
        "type": "object",
        "required": [
          "application",
          "project",
          "revision",
          "enforced",
          "network",
          "connections",
          "published",
          "modules",
          "services",
          "drift"
        ],
        "properties": {
          "application": {
            "type": "string"
          },
          "connections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Connection"
            },
            "description": "Which module may reach which, on what transport and port (from the design)."
          },
          "drift": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Differences between what Apelora intends and what Incus holds, for the whole application."
          },
          "enforced": {
            "type": "boolean",
            "description": "Connections are enforced on the application's own OVN network."
          },
          "modules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetModule"
            }
          },
          "network": {
            "type": "string"
          },
          "networkObserved": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/NetObservedNetwork",
                "description": "`None`: missing in Incus, not enforced, or Incus could not be read (see `incusError`)."
              },
              {
                "type": "null"
              }
            ]
          },
          "project": {
            "type": "string"
          },
          "published": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Published"
            }
          },
          "revision": {
            "type": "integer",
            "format": "int32",
            "description": "The deployed revision these settings come from."
          },
          "serviceRange": {
            "type": [
              "string",
              "null"
            ]
          },
          "services": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetService"
            }
          },
          "uplink": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "NetApplications": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "incusError": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why Incus could not be read; the intended side is still shown."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetApplication"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "NetBackend": {
        "type": "object",
        "required": [
          "name",
          "address",
          "instance"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "instance": {
            "type": "string",
            "description": "The instance behind it (from the backend's description)."
          },
          "name": {
            "type": "string"
          }
        }
      },
      "NetFinding": {
        "type": "object",
        "description": "Something about the settings worth knowing, from comparing them with Incus.",
        "required": [
          "severity",
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "description": "`warn`: Incus will refuse or traffic will not flow; `info`: a fact."
          }
        }
      },
      "NetModule": {
        "type": "object",
        "required": [
          "module",
          "acl",
          "internet",
          "ingress",
          "egress",
          "drift"
        ],
        "properties": {
          "acl": {
            "type": "string",
            "description": "The module's ACL and address set."
          },
          "aclPresent": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "The ACL exists in Incus; `None` when Incus could not be read."
          },
          "addresses": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "The module's instances' addresses (its address set); `None` when not read."
          },
          "drift": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "egress": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetRule"
            }
          },
          "ingress": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetRule"
            }
          },
          "internet": {
            "$ref": "#/components/schemas/Internet"
          },
          "module": {
            "type": "string"
          }
        }
      },
      "NetObservedNetwork": {
        "type": "object",
        "required": [
          "kind",
          "status"
        ],
        "properties": {
          "ipv4Address": {
            "type": [
              "string",
              "null"
            ]
          },
          "kind": {
            "type": "string"
          },
          "routerAddress": {
            "type": [
              "string",
              "null"
            ],
            "description": "The network's address on the uplink (`volatile.network.ipv4.address`): outside traffic\nto published addresses is routed here."
          },
          "status": {
            "type": "string"
          }
        }
      },
      "NetPort": {
        "type": "object",
        "required": [
          "transport",
          "port"
        ],
        "properties": {
          "port": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "transport": {
            "type": "string"
          }
        }
      },
      "NetProjectLimits": {
        "type": "object",
        "description": "A deploy project's network limits, as Incus reports them.",
        "required": [
          "project",
          "found",
          "restricted",
          "ownNetworks",
          "uplinks",
          "subnets"
        ],
        "properties": {
          "found": {
            "type": "boolean",
            "description": "Incus reports the project (the deploy identity can read it)."
          },
          "ownNetworks": {
            "type": "boolean",
            "description": "`features.networks`: the project has its own networks (needed for per-application OVN\nnetworks)."
          },
          "project": {
            "type": "string"
          },
          "restricted": {
            "type": "boolean"
          },
          "subnets": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "`restricted.networks.subnets`: `<uplink>:<range>` its load balancers and forwards may\nlisten on."
          },
          "uplinks": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "`restricted.networks.uplinks`: uplinks its networks may use."
          }
        }
      },
      "NetRule": {
        "type": "object",
        "description": "One ACL rule, intended or found in Incus, with how the two compare.",
        "required": [
          "action",
          "source",
          "destination",
          "protocol",
          "port",
          "description",
          "state"
        ],
        "properties": {
          "action": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "destination": {
            "type": "string"
          },
          "port": {
            "type": "string",
            "description": "Empty: any port."
          },
          "protocol": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "description": "`$<address set>` (a module's instances), `@external` (outside), or empty (any)."
          },
          "state": {
            "type": "string",
            "description": "`applied` (intended and in Incus), `missing` (intended, not in Incus), `unexpected` (in\nIncus, not intended) or `unknown` (Incus could not be read)."
          }
        }
      },
      "NetService": {
        "type": "object",
        "description": "A module's service address: one load balancer over its replicas.",
        "required": [
          "module",
          "ports",
          "published",
          "drift"
        ],
        "properties": {
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Allocated by Apelora; `None` while none is free (or before the first sync)."
          },
          "backends": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/NetBackend"
            },
            "description": "The load balancer's backends in Incus; `None` when it is missing or Incus was not read."
          },
          "drift": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "module": {
            "type": "string"
          },
          "ports": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetPort"
            }
          },
          "published": {
            "type": "boolean",
            "description": "Reachable from outside the application."
          }
        }
      },
      "NetSettings": {
        "type": "object",
        "required": [
          "source",
          "serviceAddressesUsed",
          "projects",
          "findings"
        ],
        "properties": {
          "findings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetFinding"
            }
          },
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetProjectLimits"
            }
          },
          "serviceAddressesTotal": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Addresses the range holds; `None` without a range.",
            "minimum": 0
          },
          "serviceAddressesUsed": {
            "type": "integer",
            "format": "int64",
            "description": "Service addresses held by applications."
          },
          "serviceRange": {
            "type": [
              "string",
              "null"
            ],
            "description": "`APELORA_SERVICE_ADDRESSES`; `None`: no service addresses."
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          },
          "uplink": {
            "type": [
              "string",
              "null"
            ],
            "description": "`APELORA_NETWORK_UPLINK`; `None`: connections are not enforced."
          },
          "uplinkNote": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the uplink is not shown (identity, error)."
          },
          "uplinkObserved": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/NetUplink"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "NetUplink": {
        "type": "object",
        "description": "The uplink network, as Incus reports it (read with the administrator identity).",
        "required": [
          "name",
          "kind",
          "status",
          "ipv4Routes",
          "ipv6Routes",
          "ovnRanges"
        ],
        "properties": {
          "ipv4Address": {
            "type": [
              "string",
              "null"
            ]
          },
          "ipv4Routes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "`ipv4.routes`: IPv4 ranges routed to the uplink (IPv4 service addresses must be in one)."
          },
          "ipv6Routes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "`ipv6.routes`: IPv6 ranges routed to the uplink (IPv6 service addresses must be in one)."
          },
          "kind": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "ovnRanges": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "`ipv4.ovn.ranges`: addresses OVN networks take on the uplink."
          },
          "status": {
            "type": "string"
          }
        }
      },
      "Network": {
        "type": "object",
        "required": [
          "name",
          "project",
          "kind",
          "managed",
          "status",
          "description"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "locations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Cluster members it is created on; empty when not per member (or unknown)."
          },
          "managed": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "NetworkAttachment": {
        "type": "object",
        "description": "Where an instance's NIC is attached: the application's network, with its own ACL.",
        "required": [
          "network",
          "acl",
          "uplink"
        ],
        "properties": {
          "acl": {
            "type": "string"
          },
          "network": {
            "type": "string"
          },
          "uplink": {
            "type": "string",
            "description": "Uplink network the application network is created on."
          }
        }
      },
      "NetworkList": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Network"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "NewApproval": {
        "type": "object",
        "required": [
          "action",
          "target"
        ],
        "properties": {
          "action": {
            "type": "string",
            "description": "The permission to be exercised, e.g. `hardware.delete`."
          },
          "reason": {
            "type": "string"
          },
          "target": {
            "type": "string",
            "description": "What it will be done to, e.g. `machine:rack1-07`."
          }
        }
      },
      "NewAssignment": {
        "type": "object",
        "required": [
          "principal",
          "role",
          "scope"
        ],
        "properties": {
          "conditions": {
            "$ref": "#/components/schemas/Conditions"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "RFC 3339. Assignments may expire; emergency grants must."
          },
          "principal": {
            "$ref": "#/components/schemas/PrincipalRef"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "$ref": "#/components/schemas/RoleRef"
          },
          "scope": {
            "$ref": "#/components/schemas/Scope"
          }
        }
      },
      "NewEnvironment": {
        "type": "object",
        "required": [
          "slug",
          "name",
          "kind"
        ],
        "properties": {
          "incusProject": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform administrators only: map an existing Incus project instead of the derived name.\nOnly a project named here can be adopted; one that carries another environment's marker\nnever is."
          },
          "kind": {
            "$ref": "#/components/schemas/EnvKind"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "NewGroup": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "externalName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The group's name in the source's tokens; for a directory, the group's full DN."
          },
          "externalSource": {
            "type": [
              "string",
              "null"
            ],
            "description": "Required with `externalName`: one of the `sources` the group list names."
          },
          "name": {
            "type": "string"
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "NewOrganization": {
        "type": "object",
        "required": [
          "slug",
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "NewProject": {
        "type": "object",
        "required": [
          "slug",
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "NewRole": {
        "type": "object",
        "required": [
          "name",
          "permissions"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "permissions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "NewSector": {
        "type": "object",
        "required": [
          "name",
          "site",
          "url",
          "credentials"
        ],
        "properties": {
          "credentials": {
            "type": "string",
            "description": "Names the variables `APELORA_SECTOR_<credentials>_CLIENT_CERT`, `_CLIENT_KEY` and\n`_SERVER_CERT` on the control plane. Never a file or a secret."
          },
          "name": {
            "type": "string"
          },
          "site": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "`https://host:port` of its Incus API."
          }
        }
      },
      "NewServiceIdentity": {
        "type": "object",
        "required": [
          "name",
          "kind"
        ],
        "properties": {
          "credentialRef": {
            "type": [
              "string",
              "null"
            ]
          },
          "expiresInDays": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Automation identities only: days until their token expires (1–365, default 90)."
          },
          "kind": {
            "$ref": "#/components/schemas/ServiceKind"
          },
          "name": {
            "type": "string"
          },
          "restrictions": {
            "type": "object",
            "description": "Limits recorded with the identity, such as `{\"projects\": [\"acme-prod\"]}`. Recorded and\nshown, not yet enforced."
          }
        }
      },
      "NewSession": {
        "type": "object",
        "required": [
          "kind"
        ],
        "properties": {
          "cols": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "kind": {
            "$ref": "#/components/schemas/SessionKind"
          },
          "rows": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "OidcSignIn": {
        "type": "object",
        "description": "What a browser needs to sign a person in with the identity provider: an OpenID Connect\nauthorization-code flow with PKCE for a public client. Nothing here is secret.",
        "required": [
          "issuer",
          "clientId",
          "scopes",
          "label"
        ],
        "properties": {
          "clientId": {
            "type": "string",
            "description": "The public client registered for the Fabric Console and the Studio (no client secret)."
          },
          "issuer": {
            "type": "string",
            "description": "The provider's issuer; its discovery document is at `<issuer>/.well-known/openid-configuration`."
          },
          "label": {
            "type": "string",
            "description": "What the button says after \"Sign in with\", e.g. the organisation's name."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "OperateRequest": {
        "type": "object",
        "required": [
          "action"
        ],
        "properties": {
          "action": {
            "$ref": "#/components/schemas/OperationKind"
          },
          "confirmDisruption": {
            "type": "boolean",
            "description": "Required to stop or restart an application that has single-instance or stateful\nmodules: it acknowledges that their clients lose service meanwhile."
          },
          "target": {
            "type": [
              "string",
              "null"
            ],
            "description": "The server to move the application to. Needed for `migrate`, ignored otherwise."
          }
        }
      },
      "OperationAccepted": {
        "type": "object",
        "required": [
          "operation",
          "created"
        ],
        "properties": {
          "created": {
            "type": "boolean",
            "description": "False when the same `Idempotency-Key` had already created it."
          },
          "operation": {
            "$ref": "#/components/schemas/OperationDto"
          }
        }
      },
      "OperationDto": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "state",
          "requestedBy",
          "createdAt",
          "phases",
          "stepsDone",
          "stepsTotal"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "finishedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "$ref": "#/components/schemas/OperationKind"
          },
          "phases": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PhaseDto"
            }
          },
          "requestedBy": {
            "type": "string"
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "state": {
            "$ref": "#/components/schemas/OperationState"
          },
          "stepsDone": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "stepsTotal": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "OperationKind": {
        "type": "string",
        "enum": [
          "start",
          "stop",
          "shutdown",
          "restart",
          "migrate",
          "update"
        ]
      },
      "OperationList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OperationDto"
            }
          }
        }
      },
      "OperationState": {
        "type": "string",
        "enum": [
          "pending",
          "running",
          "succeeded",
          "failed",
          "cancelled"
        ]
      },
      "OperationSummary": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "state",
          "createdAt"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "$ref": "#/components/schemas/OperationKind"
          },
          "state": {
            "$ref": "#/components/schemas/OperationState"
          }
        }
      },
      "OrganizationDto": {
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "createdAt",
          "disabled"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "disabled": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "OrganizationList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrganizationDto"
            }
          }
        }
      },
      "OrphanList": {
        "type": "object",
        "required": [
          "source",
          "projects",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrphanVolume"
            }
          },
          "projects": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The projects looked at (Apelora's deploy projects)."
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "OrphanVolume": {
        "type": "object",
        "required": [
          "project",
          "pool",
          "name",
          "member",
          "content",
          "usedBy",
          "createdAt",
          "reason"
        ],
        "properties": {
          "application": {
            "type": [
              "string",
              "null"
            ],
            "description": "`user.apelora.application`, when Apelora created it."
          },
          "backupOf": {
            "type": [
              "string",
              "null"
            ],
            "description": "`user.apelora.backup-of`, for a backup copy."
          },
          "content": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "member": {
            "type": "string",
            "description": "Member of a member-local pool; empty otherwise."
          },
          "name": {
            "type": "string"
          },
          "pool": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "reason": {
            "type": "string",
            "description": "Why it is listed, in words."
          },
          "sizeMib": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Size as configured, `None` when Incus reports none in a unit Apelora reads.",
            "minimum": 0
          },
          "usedBy": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Owner": {
        "type": "object",
        "description": "The application and module an instance belongs to.",
        "required": [
          "application",
          "module"
        ],
        "properties": {
          "application": {
            "type": "string"
          },
          "module": {
            "type": "string"
          },
          "replica": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "PasswordChangeRequest": {
        "type": "object",
        "required": [
          "current",
          "new"
        ],
        "properties": {
          "current": {
            "type": "string"
          },
          "new": {
            "type": "string"
          }
        }
      },
      "PasswordSetupRequest": {
        "type": "object",
        "required": [
          "token",
          "password"
        ],
        "properties": {
          "password": {
            "type": "string"
          },
          "token": {
            "type": "string",
            "description": "The token from the setup link."
          }
        }
      },
      "PasswordSignInRequest": {
        "type": "object",
        "required": [
          "username",
          "password"
        ],
        "properties": {
          "directory": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Sign in against this directory instead of a local account."
          },
          "password": {
            "type": "string"
          },
          "username": {
            "type": "string"
          }
        }
      },
      "PasswordSignInResult": {
        "type": "object",
        "required": [
          "token",
          "expiresAt",
          "name"
        ],
        "properties": {
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339; the session also ends after an hour without use."
          },
          "name": {
            "type": "string",
            "description": "The person's display name, or their username."
          },
          "token": {
            "type": "string",
            "description": "The session token (`apu_…`), sent as `Authorization: Bearer`. Shown only here."
          }
        }
      },
      "PendingJoin": {
        "type": "object",
        "description": "A join token that has been issued and not yet used, revoked or expired (no secret).",
        "required": [
          "memberName",
          "expiresAt"
        ],
        "properties": {
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339, as Incus reports it."
          },
          "memberName": {
            "type": "string"
          }
        }
      },
      "Permission": {
        "type": "string",
        "enum": [
          "read-inventory",
          "read-audit",
          "manage-tokens",
          "manage-infrastructure",
          "design-applications",
          "deploy"
        ]
      },
      "PermissionDto": {
        "type": "object",
        "required": [
          "id",
          "class",
          "floor",
          "needsApproval",
          "description"
        ],
        "properties": {
          "class": {
            "$ref": "#/components/schemas/Class"
          },
          "description": {
            "type": "string"
          },
          "floor": {
            "$ref": "#/components/schemas/Level",
            "description": "The narrowest scope level at which a grant takes effect."
          },
          "id": {
            "type": "string"
          },
          "needsApproval": {
            "type": "boolean"
          }
        }
      },
      "PermissionList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PermissionDto"
            }
          }
        }
      },
      "PersonalToken": {
        "type": "object",
        "required": [
          "id",
          "name",
          "userId",
          "owner",
          "state",
          "createdAt",
          "expiresAt",
          "current"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "current": {
            "type": "boolean",
            "description": "The request was made with this token."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "owner": {
            "type": "string"
          },
          "revokedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "revokedBy": {
            "type": [
              "string",
              "null"
            ],
            "description": "Who revoked it (`user:…`), or `disabled` when its person was disabled."
          },
          "rotatedFrom": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The token this one replaced."
          },
          "state": {
            "type": "string",
            "description": "`active`, `rotating` (replaced, working until `expiresAt`), `expired` or `revoked`."
          },
          "successor": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The token that replaced this one."
          },
          "userId": {
            "type": "string",
            "format": "uuid",
            "description": "The person it acts as."
          }
        }
      },
      "PersonalTokenCreated": {
        "type": "object",
        "required": [
          "token",
          "info"
        ],
        "properties": {
          "info": {
            "$ref": "#/components/schemas/PersonalToken"
          },
          "token": {
            "type": "string",
            "description": "The token itself, shown only in this response."
          }
        }
      },
      "PersonalTokenList": {
        "type": "object",
        "required": [
          "items",
          "limit"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PersonalToken"
            }
          },
          "limit": {
            "type": "integer",
            "format": "int64",
            "description": "Live tokens a person may have at once."
          }
        }
      },
      "PersonalTokenRotated": {
        "type": "object",
        "required": [
          "token",
          "info",
          "previous"
        ],
        "properties": {
          "info": {
            "$ref": "#/components/schemas/PersonalToken"
          },
          "previous": {
            "$ref": "#/components/schemas/PersonalToken",
            "description": "The old token, now expiring at the end of the overlap."
          },
          "token": {
            "type": "string",
            "description": "The successor's token, shown only in this response."
          }
        }
      },
      "PhaseDto": {
        "type": "object",
        "required": [
          "action",
          "state",
          "steps"
        ],
        "properties": {
          "action": {
            "type": "string",
            "description": "`start` or `stop`."
          },
          "state": {
            "type": "string"
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StepDto"
            }
          }
        }
      },
      "Plan": {
        "type": "object",
        "required": [
          "items",
          "warnings"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlanItem"
            }
          },
          "quota": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/QuotaCheck",
                "description": "The deployment against the quotas above its environment; absent when no\nquota applies. `allowed: false` means applying is refused."
              },
              {
                "type": "null"
              }
            ]
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Facts the designer should know before applying, e.g. single points of failure."
          }
        }
      },
      "PlanAction": {
        "type": "string",
        "enum": [
          "create",
          "keep",
          "resize",
          "replace",
          "rebuild",
          "remove",
          "conflict"
        ]
      },
      "PlanItem": {
        "type": "object",
        "required": [
          "module",
          "replica",
          "instance",
          "action",
          "reason"
        ],
        "properties": {
          "action": {
            "$ref": "#/components/schemas/PlanAction"
          },
          "changes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LimitChange"
            },
            "description": "For `resize`: each limit that changes."
          },
          "instance": {
            "type": "string"
          },
          "module": {
            "type": "string",
            "description": "The module in the design (for `remove`: the label of the instance being removed)."
          },
          "outdated": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What the running instance was built from that the design now asks differently:\n`image`, `settings` or `storage`. A stateless replica is replaced (`replace`); a singleton\nor stateful module is kept as it is (updating those is not built yet)."
          },
          "reason": {
            "type": "string",
            "description": "Why, in a sentence (e.g. what the conflicting instance is)."
          },
          "replica": {
            "type": "integer",
            "format": "int32",
            "description": "1-based replica number.",
            "minimum": 0
          }
        }
      },
      "PlanRequest": {
        "type": "object",
        "required": [
          "project",
          "modules"
        ],
        "properties": {
          "connections": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/Connection"
            },
            "description": "The design's connections; enforced when the control plane has a network uplink."
          },
          "modules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DesiredModule"
            }
          },
          "project": {
            "type": "string"
          },
          "published": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Published"
            },
            "description": "Ports reachable from outside the application (needs connections to be enforced)."
          }
        }
      },
      "PolicyDto": {
        "type": "object",
        "required": [
          "id",
          "name",
          "kind",
          "parameters",
          "enabled",
          "updatedBy",
          "updatedAt"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "description": "`mfa` or `approval`."
          },
          "name": {
            "type": "string"
          },
          "parameters": {
            "type": "object",
            "description": "For `mfa`: `environments` (a list of `production`, `staging`, `development`, `other`)\nand/or `infrastructure` (`true` or `false`). For `approval`: `actions`, the permission ids\nthat need an approval."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedBy": {
            "type": "string"
          }
        }
      },
      "PolicyList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PolicyDto"
            }
          }
        }
      },
      "PowerOff": {
        "type": "object",
        "description": "One recorded power-off of a failed server through its baseboard management controller (BMC).\nThe BMC's address is not included.",
        "required": [
          "at",
          "member",
          "outcome",
          "summary"
        ],
        "properties": {
          "at": {
            "type": "string"
          },
          "member": {
            "type": "string"
          },
          "outcome": {
            "type": "string",
            "description": "`success`, `failed` or `denied`."
          },
          "summary": {
            "type": "string"
          }
        }
      },
      "PreflightReport": {
        "type": "object",
        "required": [
          "source",
          "overall",
          "checks"
        ],
        "properties": {
          "checks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Check"
            }
          },
          "overall": {
            "$ref": "#/components/schemas/CheckStatus",
            "description": "The worst status among the checks."
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "PrincipalRef": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "id",
              "type"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "type": {
                "type": "string",
                "enum": [
                  "user"
                ]
              }
            }
          },
          {
            "type": "object",
            "required": [
              "id",
              "type"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "type": {
                "type": "string",
                "enum": [
                  "group"
                ]
              }
            }
          },
          {
            "type": "object",
            "required": [
              "id",
              "type"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "type": {
                "type": "string",
                "enum": [
                  "service"
                ]
              }
            }
          }
        ],
        "description": "Who an assignment is for."
      },
      "Probe": {
        "type": "object",
        "description": "The result of probing one mirror: its state and a short reason, never internals.",
        "required": [
          "state",
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string",
            "description": "e.g. `HTTP 200`, `no answer within 3 s`."
          },
          "state": {
            "$ref": "#/components/schemas/ProbeState"
          }
        }
      },
      "ProbeState": {
        "type": "string",
        "description": "Whether a mirror answered its probe.",
        "enum": [
          "answers",
          "fails",
          "not-checked"
        ]
      },
      "Project": {
        "type": "object",
        "required": [
          "name",
          "description",
          "restricted"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "restricted": {
            "type": "boolean",
            "description": "`restricted=true`: the project limits what its instances may do."
          }
        }
      },
      "ProjectDto": {
        "type": "object",
        "required": [
          "id",
          "organizationId",
          "organizationSlug",
          "slug",
          "name",
          "createdAt"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "organizationId": {
            "type": "string",
            "format": "uuid"
          },
          "organizationSlug": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "ProjectList": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Project"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "ProjectRef": {
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "organizationId",
          "organizationSlug"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "organizationId": {
            "type": "string",
            "format": "uuid"
          },
          "organizationSlug": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "ProviderCheck": {
        "type": "object",
        "required": [
          "authorizationEndpoint",
          "tokenEndpoint",
          "jwksUri",
          "keys"
        ],
        "properties": {
          "authorizationEndpoint": {
            "type": "string"
          },
          "jwksUri": {
            "type": "string"
          },
          "keys": {
            "type": "integer",
            "description": "Signing keys the provider publishes now.",
            "minimum": 0
          },
          "tokenEndpoint": {
            "type": "string"
          }
        }
      },
      "ProviderInput": {
        "type": "object",
        "description": "The editable fields of a provider. Lists default to the provider defaults when left empty.",
        "required": [
          "name",
          "issuer",
          "audiences"
        ],
        "properties": {
          "audiences": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "authorizedParties": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "clientId": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "groupsClaim": {
            "type": [
              "string",
              "null"
            ]
          },
          "issuer": {
            "type": "string"
          },
          "mfaAcr": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "mfaAmr": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "name": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "usernameClaim": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ProviderMode": {
        "type": "string",
        "description": "Where the backend's view of the infrastructure comes from.",
        "enum": [
          "mock",
          "incus"
        ]
      },
      "ProviderSource": {
        "type": "string",
        "enum": [
          "console",
          "environment"
        ]
      },
      "ProviderView": {
        "type": "object",
        "required": [
          "source",
          "name",
          "issuer",
          "audiences",
          "scopes",
          "groupsClaim",
          "usernameClaim",
          "mfaAmr",
          "mfaAcr",
          "authorizedParties",
          "enabled",
          "reachable"
        ],
        "properties": {
          "audiences": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "authorizedParties": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "clientId": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "groupsClaim": {
            "type": "string"
          },
          "id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "None for the environment's provider."
          },
          "issuer": {
            "type": "string"
          },
          "mfaAcr": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "mfaAmr": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "name": {
            "type": "string"
          },
          "reachable": {
            "type": "boolean",
            "description": "Whether its key set could be read at the last reload; the reason when not."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "source": {
            "$ref": "#/components/schemas/ProviderSource"
          },
          "updatedBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "usernameClaim": {
            "type": "string"
          }
        }
      },
      "ProvisionerKind": {
        "type": "string",
        "description": "What installs and powers a machine. Every provisioner enrols the same way.",
        "enum": [
          "manual",
          "maas"
        ]
      },
      "PublishRequest": {
        "type": "object",
        "properties": {
          "label": {
            "type": [
              "string",
              "null"
            ],
            "description": "A short name for the version, e.g. `after load test`."
          }
        }
      },
      "Published": {
        "type": "object",
        "description": "A port of a module reachable from outside the application (in the Studio: connected\nfrom a gateway). Only ports with a number can be published.",
        "required": [
          "module",
          "transport",
          "port"
        ],
        "properties": {
          "module": {
            "type": "string"
          },
          "port": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "transport": {
            "type": "string",
            "description": "`tcp` or `udp`."
          }
        }
      },
      "QueuedChange": {
        "type": "object",
        "required": [
          "module",
          "instance",
          "action",
          "jobId"
        ],
        "properties": {
          "action": {
            "$ref": "#/components/schemas/PlanAction"
          },
          "instance": {
            "type": "string"
          },
          "jobId": {
            "type": "string",
            "format": "uuid"
          },
          "module": {
            "type": "string"
          }
        }
      },
      "QuotaChange": {
        "type": "object",
        "description": "The result of changing a quota.",
        "required": [
          "environments"
        ],
        "properties": {
          "environments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenancyLimitOutcome"
            },
            "description": "Each environment beneath the scope: what mirroring the change to Incus did."
          },
          "quota": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/QuotaLimits"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "QuotaCheck": {
        "type": "object",
        "description": "A deployment against the quotas above its environment.",
        "required": [
          "allowed",
          "adding",
          "scopes"
        ],
        "properties": {
          "adding": {
            "$ref": "#/components/schemas/QuotaUsage",
            "description": "What it adds (instances to create; removals are not credited before they happen)."
          },
          "allowed": {
            "type": "boolean",
            "description": "False when any limited dimension would be exceeded: the deployment is refused."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuotaScopeCheck"
            }
          }
        }
      },
      "QuotaDimension": {
        "type": "string",
        "description": "One quota dimension.",
        "enum": [
          "instances",
          "cpu",
          "memory",
          "disk"
        ]
      },
      "QuotaDimensionCheck": {
        "type": "object",
        "required": [
          "dimension",
          "used",
          "adding",
          "limit",
          "exceeded"
        ],
        "properties": {
          "adding": {
            "type": "integer",
            "format": "int64",
            "description": "What the deployment adds."
          },
          "dimension": {
            "$ref": "#/components/schemas/QuotaDimension"
          },
          "exceeded": {
            "type": "boolean"
          },
          "limit": {
            "type": "integer",
            "format": "int64"
          },
          "used": {
            "type": "integer",
            "format": "int64",
            "description": "In use now (instances, CPUs or bytes)."
          }
        }
      },
      "QuotaLimits": {
        "type": "object",
        "description": "A quota: one limit per dimension, `None` meaning no limit.",
        "properties": {
          "cpu": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "diskGib": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "instances": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "memoryGib": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          }
        }
      },
      "QuotaScopeCheck": {
        "type": "object",
        "required": [
          "kind",
          "id",
          "name",
          "dimensions"
        ],
        "properties": {
          "dimensions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuotaDimensionCheck"
            },
            "description": "Only the dimensions this scope limits."
          },
          "id": {
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/QuotaScopeKind"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "QuotaScopeKind": {
        "type": "string",
        "description": "Which level of the tenancy tree a quota belongs to.",
        "enum": [
          "organization",
          "project",
          "environment"
        ]
      },
      "QuotaUsage": {
        "type": "object",
        "description": "Resources in use or asked for, in Incus's units.",
        "required": [
          "instances",
          "cpu",
          "memoryBytes",
          "diskBytes"
        ],
        "properties": {
          "cpu": {
            "type": "integer",
            "format": "int64"
          },
          "diskBytes": {
            "type": "integer",
            "format": "int64"
          },
          "instances": {
            "type": "integer",
            "format": "int64"
          },
          "memoryBytes": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "QuotaView": {
        "type": "object",
        "description": "A scope's quota, its use and the quotas above it.",
        "required": [
          "kind",
          "id",
          "name",
          "bound",
          "canSet"
        ],
        "properties": {
          "bound": {
            "$ref": "#/components/schemas/QuotaLimits",
            "description": "The tightest quota of the scopes above (a tenant may not set more)."
          },
          "canSet": {
            "type": "boolean",
            "description": "The caller may change it."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "$ref": "#/components/schemas/QuotaScopeKind"
          },
          "name": {
            "type": "string"
          },
          "quota": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/QuotaLimits",
                "description": "`None`: this scope has no quota of its own."
              },
              {
                "type": "null"
              }
            ]
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updatedBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "usage": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/QuotaUsage",
                "description": "Use beneath this scope as Incus reports it; `None` with `usageError` when it could not be read."
              },
              {
                "type": "null"
              }
            ]
          },
          "usageError": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Readiness": {
        "type": "object",
        "description": "What to run inside the instance and how long it may take.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Program and arguments, as an argument list (no shell). Exit status 0 means ready."
          },
          "timeoutSecs": {
            "type": "integer",
            "format": "int32",
            "description": "Longer than this counts as failing (1–15, default 5).",
            "minimum": 0
          }
        }
      },
      "RebalanceMove": {
        "type": "object",
        "description": "One replica to move so a module is spread again.",
        "required": [
          "project",
          "application",
          "module",
          "instance",
          "from",
          "target",
          "live",
          "reason"
        ],
        "properties": {
          "application": {
            "type": "string"
          },
          "from": {
            "type": "string"
          },
          "instance": {
            "type": "string"
          },
          "live": {
            "type": "boolean",
            "description": "A virtual machine moves while it runs. A container stops briefly, then starts."
          },
          "module": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "target": {
            "type": "string"
          }
        }
      },
      "RecoveryAction": {
        "type": "string",
        "description": "What becomes of one instance of a failed member.",
        "enum": [
          "restart",
          "after-fencing",
          "substitute",
          "wait"
        ]
      },
      "RecoveryItem": {
        "type": "object",
        "required": [
          "project",
          "instance",
          "action",
          "reason"
        ],
        "properties": {
          "action": {
            "$ref": "#/components/schemas/RecoveryAction"
          },
          "application": {
            "type": [
              "string",
              "null"
            ]
          },
          "instance": {
            "type": "string"
          },
          "module": {
            "type": [
              "string",
              "null"
            ]
          },
          "project": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "target": {
            "type": [
              "string",
              "null"
            ],
            "description": "The member it restarts on (as chosen now; the job chooses again when it runs)."
          }
        }
      },
      "RecoveryMember": {
        "type": "object",
        "description": "One failed member: its fencing and what happens to each of its instances.",
        "required": [
          "member",
          "status",
          "fencing",
          "items"
        ],
        "properties": {
          "confirmedBy": {
            "type": [
              "string",
              "null"
            ],
            "description": "Who confirmed the server is powered off, when someone did."
          },
          "decidedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the recovery decision was recorded (once per failure)."
          },
          "detectedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When Apelora noticed (RFC 3339)."
          },
          "evidence": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/FenceEvidence"
              },
              {
                "type": "null"
              }
            ]
          },
          "failure": {
            "type": [
              "string",
              "null"
            ],
            "description": "The failure record; `None` until the supervisor has seen it."
          },
          "fencedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "fencing": {
            "$ref": "#/components/schemas/FenceView"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RecoveryItem"
            }
          },
          "lastHeartbeat": {
            "type": [
              "string",
              "null"
            ],
            "description": "Incus's last heartbeat from it (RFC 3339), when its message gives one."
          },
          "member": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Incus's status (`Offline` while it is failed)."
          }
        }
      },
      "RecoveryReport": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RecoveryMember"
            },
            "description": "Failed members, by name."
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "RegisterMachine": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "The name it will have as a cluster member."
          },
          "provider": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ProvisionerKind",
                "description": "Defaults to `manual`."
              },
              {
                "type": "null"
              }
            ]
          },
          "systemId": {
            "type": [
              "string",
              "null"
            ],
            "description": "For a `maas` machine: its MAAS system id (from `GET /api/v1/provisioners/maas/machines`)."
          }
        }
      },
      "RemovalPlan": {
        "type": "object",
        "required": [
          "member",
          "status",
          "instances",
          "volumes",
          "blocked",
          "warnings"
        ],
        "properties": {
          "blocked": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Why removing it now is refused; empty when it may proceed."
          },
          "instances": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Instances still on it (`project/name`)."
          },
          "member": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "The member's status now (`Evacuated`, `Online`, `Offline`…)."
          },
          "volumes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Application volumes on it (`project/volume`)."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Consequences to accept before proceeding."
          }
        }
      },
      "RemovalPreview": {
        "type": "object",
        "required": [
          "source",
          "plan"
        ],
        "properties": {
          "plan": {
            "$ref": "#/components/schemas/RemovalPlan"
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "ReplicaSummary": {
        "type": "object",
        "required": [
          "desired",
          "running",
          "healthy",
          "unhealthy"
        ],
        "properties": {
          "desired": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "healthy": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "running": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "unhealthy": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "RestorePlan": {
        "type": "object",
        "description": "What restoring a volume from one of its backups would do (the dry run of a restore). The\nrestore copies the backup over the volume (an Incus `refresh` copy): everything written since\nthe backup is replaced and the volume's own snapshots are deleted, so a safety backup of the\ncurrent data is taken first unless the person says otherwise.",
        "required": [
          "volume",
          "pool",
          "member",
          "sizeMib",
          "backup",
          "backupPool",
          "backupMember",
          "backupTakenAt",
          "snapshotsDeleted",
          "usedBy",
          "running",
          "blocked",
          "steps"
        ],
        "properties": {
          "backup": {
            "type": "string"
          },
          "backupMember": {
            "type": "string"
          },
          "backupPool": {
            "type": "string"
          },
          "backupTakenAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the backup was taken (RFC 3339): everything written after it is replaced."
          },
          "blocked": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Why the restore cannot run now; empty when it can."
          },
          "member": {
            "type": "string",
            "description": "Member of a member-local pool; empty on a standalone server."
          },
          "pool": {
            "type": "string"
          },
          "running": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Of those, the ones running now: they must be stopped first."
          },
          "safetyBackupPool": {
            "type": [
              "string",
              "null"
            ],
            "description": "The pool a safety backup of the current data goes to; `None` when none is taken."
          },
          "sizeMib": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "snapshotsDeleted": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The volume's own snapshots, which the restore deletes."
          },
          "steps": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What the restore job will do, in order."
          },
          "usedBy": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Instances using the volume."
          },
          "volume": {
            "type": "string",
            "description": "The volume to overwrite (Incus name): what to type to confirm."
          }
        }
      },
      "RestorePreview": {
        "type": "object",
        "required": [
          "source",
          "plan"
        ],
        "properties": {
          "plan": {
            "$ref": "#/components/schemas/RestorePlan"
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "RestoreVolumeRequest": {
        "type": "object",
        "required": [
          "confirm"
        ],
        "properties": {
          "confirm": {
            "type": "string",
            "description": "The volume's Incus name again, typed by the person restoring it."
          },
          "safetyBackup": {
            "type": "boolean",
            "description": "Take a safety backup of the current data first (default true)."
          }
        }
      },
      "Role": {
        "type": "string",
        "description": "Who may do what. Every API route names the permission it needs; roles map to permissions\nhere and nowhere else.",
        "enum": [
          "fabric-admin",
          "operator",
          "studio-designer",
          "auditor"
        ]
      },
      "RoleDto": {
        "type": "object",
        "required": [
          "key",
          "reference",
          "name",
          "description",
          "builtin",
          "permissions",
          "scopes"
        ],
        "properties": {
          "builtin": {
            "type": "boolean"
          },
          "description": {
            "type": "string"
          },
          "key": {
            "type": "string",
            "description": "Unique among roles (`builtin:<key>` or `custom:<uuid>`), for keeping lists and links\napart. Assignments and the other role operations take `reference` (a custom role's bare\nid), never this key."
          },
          "name": {
            "type": "string"
          },
          "permissions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "reference": {
            "$ref": "#/components/schemas/RoleRef",
            "description": "The role to name in assignments, grants and deletion."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Level"
            },
            "description": "Scope levels it can be assigned at."
          }
        }
      },
      "RoleGrant": {
        "type": "object",
        "required": [
          "role",
          "scope",
          "viaGroup",
          "emergency"
        ],
        "properties": {
          "emergency": {
            "type": "boolean"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "RFC 3339."
          },
          "role": {
            "type": "string"
          },
          "scope": {
            "$ref": "#/components/schemas/Scope"
          },
          "viaGroup": {
            "type": "boolean"
          }
        }
      },
      "RoleList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoleDto"
            }
          }
        }
      },
      "RoleRef": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "key",
              "type"
            ],
            "properties": {
              "key": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "builtin"
                ]
              }
            }
          },
          {
            "type": "object",
            "required": [
              "id",
              "type"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "type": {
                "type": "string",
                "enum": [
                  "custom"
                ]
              }
            }
          }
        ]
      },
      "RotatePersonalToken": {
        "type": "object",
        "properties": {
          "expiresInDays": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "The successor's lifetime, 1–365 days; the old token's lifetime when omitted."
          },
          "overlapMinutes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "How long the old token keeps working, 0–1440 minutes; 60 when omitted."
          }
        }
      },
      "SaveDraft": {
        "type": "object",
        "required": [
          "document"
        ],
        "properties": {
          "baseVersion": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "The draft version this edit started from; omit only for the first save."
          },
          "document": {
            "type": "object",
            "description": "A Studio document (the application assembly format the Studio imports and exports)."
          }
        }
      },
      "SavePolicy": {
        "type": "object",
        "required": [
          "name",
          "kind",
          "parameters"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "kind": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "parameters": {
            "type": "object",
            "description": "For `mfa`: `environments` (a list of `production`, `staging`, `development`, `other`)\nand/or `infrastructure` (`true` or `false`). For `approval`: `actions`, the permission ids\nthat need an approval."
          }
        }
      },
      "Schedule": {
        "type": "object",
        "description": "How often something is done for a volume and how many results are kept.",
        "required": [
          "everyMinutes",
          "keep"
        ],
        "properties": {
          "everyMinutes": {
            "type": "integer",
            "format": "int32",
            "description": "Minutes between two runs: 15 minutes to one week.",
            "minimum": 0
          },
          "keep": {
            "type": "integer",
            "format": "int32",
            "description": "How many of the scheduled results are kept: 1 to 50.",
            "minimum": 0
          }
        }
      },
      "ScheduleState": {
        "type": "object",
        "description": "A schedule as set, and how its last run went.",
        "required": [
          "everyMinutes",
          "keep"
        ],
        "properties": {
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the last run failed; cleared by the next success."
          },
          "everyMinutes": {
            "type": "integer",
            "format": "int32"
          },
          "keep": {
            "type": "integer",
            "format": "int32"
          },
          "lastRunAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last ran successfully (RFC 3339)."
          }
        }
      },
      "Scope": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "platform"
                ]
              }
            }
          },
          {
            "type": "object",
            "required": [
              "id",
              "type"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "type": {
                "type": "string",
                "enum": [
                  "organization"
                ]
              }
            }
          },
          {
            "type": "object",
            "required": [
              "id",
              "type"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "type": {
                "type": "string",
                "enum": [
                  "project"
                ]
              }
            }
          },
          {
            "type": "object",
            "required": [
              "id",
              "type"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "type": {
                "type": "string",
                "enum": [
                  "application"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "A named group of physical machines (a MAAS resource pool, if MAAS is adopted).",
            "required": [
              "name",
              "type"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "pool"
                ]
              }
            }
          }
        ]
      },
      "SectorInfo": {
        "type": "object",
        "description": "One sector as the Servers area shows it.",
        "required": [
          "name",
          "site",
          "home",
          "state",
          "credentialVars"
        ],
        "properties": {
          "addedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "addedBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "credentialVars": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "For a registered sector: the variables that must name its identity's files."
          },
          "detail": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it is not connected, in a sentence."
          },
          "home": {
            "type": "boolean",
            "description": "The sector this control plane runs against (`APELORA_SITE`, `APELORA_SECTOR`)."
          },
          "incusVersion": {
            "type": [
              "string",
              "null"
            ]
          },
          "members": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Members of its cluster (1 for a standalone server); `null` when it did not answer.",
            "minimum": 0
          },
          "name": {
            "type": "string"
          },
          "site": {
            "type": "string"
          },
          "state": {
            "$ref": "#/components/schemas/SectorState"
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its Incus API; `null` for the home sector (`APELORA_INCUS_URL`, a setting)."
          },
          "warning": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SectorList": {
        "type": "object",
        "required": [
          "source",
          "items",
          "note"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SectorInfo"
            },
            "description": "The home sector first, then the registered ones by site and name."
          },
          "note": {
            "type": "string",
            "description": "Applications deploy only to the home sector in this version."
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "SectorState": {
        "type": "string",
        "enum": [
          "connected",
          "unreachable",
          "not-configured"
        ]
      },
      "ServerInfo": {
        "type": "object",
        "description": "Facts about the Incus server the adapter is talking to.",
        "required": [
          "apiVersion",
          "serverVersion",
          "kernelVersion",
          "apiExtensions",
          "clustered",
          "auth"
        ],
        "properties": {
          "apiExtensions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "apiVersion": {
            "type": "string"
          },
          "architectures": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Architectures this server can run (`environment.architectures`); empty when unknown."
          },
          "auth": {
            "type": "string"
          },
          "clustered": {
            "type": "boolean"
          },
          "kernelVersion": {
            "type": [
              "string",
              "null"
            ],
            "description": "`None` when unknown (e.g. the mock provider)."
          },
          "serverVersion": {
            "type": [
              "string",
              "null"
            ],
            "description": "`None` when unknown (e.g. the mock provider)."
          }
        }
      },
      "ServiceIdentityCreated": {
        "type": "object",
        "required": [
          "identity"
        ],
        "properties": {
          "identity": {
            "$ref": "#/components/schemas/ServiceIdentityDto"
          },
          "token": {
            "type": [
              "string",
              "null"
            ],
            "description": "The API token of an automation identity, shown only here."
          }
        }
      },
      "ServiceIdentityDto": {
        "type": "object",
        "required": [
          "id",
          "name",
          "kind",
          "backend",
          "operations",
          "restrictions",
          "createdBy",
          "createdAt",
          "disabled",
          "apiAccess"
        ],
        "properties": {
          "apiAccess": {
            "type": "boolean",
            "description": "Can call the Apelora API (automation identities only)."
          },
          "backend": {
            "type": "string",
            "description": "The system it authenticates to."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string"
          },
          "credentialRef": {
            "type": [
              "string",
              "null"
            ],
            "description": "Name of the credential in the backend's secret store (never the secret)."
          },
          "disabled": {
            "type": "boolean"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "$ref": "#/components/schemas/ServiceKind"
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "operations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The operation families this kind may perform."
          },
          "restrictions": {
            "type": "object",
            "description": "Limits recorded with the identity, such as `{\"projects\": [\"acme-prod\"]}`. Recorded and\nshown, not yet enforced."
          }
        }
      },
      "ServiceIdentityList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceIdentityDto"
            }
          }
        }
      },
      "ServiceKind": {
        "type": "string",
        "enum": [
          "workload",
          "network",
          "storage",
          "provisioning",
          "automation"
        ]
      },
      "ServiceStatus": {
        "type": "object",
        "description": "A stateless module's service address: a load balancer over its healthy replicas.",
        "required": [
          "module",
          "project",
          "address"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "module": {
            "type": "string"
          },
          "project": {
            "type": "string"
          }
        }
      },
      "SessionInfo": {
        "type": "object",
        "required": [
          "id",
          "application",
          "instance",
          "kind",
          "person",
          "startedAt",
          "endsBy",
          "lastActivityAt",
          "idleEndsAt",
          "mine"
        ],
        "properties": {
          "application": {
            "type": "string"
          },
          "endsBy": {
            "type": "string",
            "description": "The absolute limit: the session ends then whatever happens."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "idleEndsAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the session ends unless the person types before then."
          },
          "instance": {
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/SessionKind"
          },
          "lastActivityAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the person last typed (the start until they do)."
          },
          "mine": {
            "type": "boolean",
            "description": "The caller's own session."
          },
          "person": {
            "type": "string"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SessionKind": {
        "type": "string",
        "description": "What a person can open on a module.",
        "enum": [
          "terminal",
          "powershell",
          "rdp"
        ]
      },
      "SessionList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SessionInfo"
            }
          }
        }
      },
      "SessionTicket": {
        "type": "object",
        "required": [
          "id",
          "ticket",
          "expiresAt",
          "connectPath",
          "protocol",
          "kind",
          "instance",
          "idleSecs",
          "maxSecs",
          "provider"
        ],
        "properties": {
          "connectPath": {
            "type": "string",
            "description": "Path of the websocket, relative to the API."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "idleSecs": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "instance": {
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/SessionKind"
          },
          "maxSecs": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "protocol": {
            "type": "string"
          },
          "provider": {
            "$ref": "#/components/schemas/ProviderMode",
            "description": "Where the instance lives: a `mock` provider's sessions talk to a labelled fake shell."
          },
          "ticket": {
            "type": "string",
            "description": "Shown once. Present it as the `ticket.<value>` sub-protocol when opening the websocket;\nnever put it in a URL."
          }
        }
      },
      "SetVolumeSchedules": {
        "type": "object",
        "properties": {
          "backups": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Schedule",
                "description": "Scheduled backups (into the backup pool, on another member); `null` turns them off."
              },
              {
                "type": "null"
              }
            ]
          },
          "snapshots": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Schedule",
                "description": "Scheduled snapshots (`auto-…`, in the volume's pool); `null` turns them off."
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "SettingChange": {
        "type": "object",
        "description": "One setting in a change: what it is now, what it becomes, and what to know first.",
        "required": [
          "key",
          "label",
          "warnings"
        ],
        "properties": {
          "from": {
            "type": [
              "string",
              "null"
            ],
            "description": "The value set now; absent when Incus's default applies."
          },
          "key": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "to": {
            "type": [
              "string",
              "null"
            ],
            "description": "The value after the change; absent when the setting is removed."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "SettingsChangeReport": {
        "type": "object",
        "required": [
          "applied",
          "changes",
          "approvalTarget"
        ],
        "properties": {
          "applied": {
            "type": "boolean",
            "description": "False for a dry run."
          },
          "approvalTarget": {
            "type": "string",
            "description": "The approval target to ask for (`POST /approvals`, action `cluster.sensitive_change`)."
          },
          "changes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SettingChange"
            }
          }
        }
      },
      "SettingsWorker": {
        "type": "object",
        "required": [
          "id",
          "host",
          "version",
          "lastSeen"
        ],
        "properties": {
          "host": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "lastSeen": {
            "type": "string",
            "description": "RFC 3339."
          },
          "version": {
            "type": "string"
          }
        }
      },
      "SignInOptions": {
        "type": "object",
        "required": [
          "providers",
          "apiTokens",
          "localAccounts",
          "directories"
        ],
        "properties": {
          "apiTokens": {
            "type": "boolean",
            "description": "Whether API tokens are accepted (legacy platform-wide tokens)."
          },
          "directories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DirectoryOption"
            },
            "description": "Directories people can sign in with (username and password), enabled ones only."
          },
          "localAccounts": {
            "type": "boolean",
            "description": "Whether people can sign in with a local account (username and password)."
          },
          "providers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OidcSignIn"
            },
            "description": "The organisation's identity providers people can sign in with, in order."
          }
        }
      },
      "SignInSettings": {
        "type": "object",
        "required": [
          "providers",
          "apiTokens",
          "localAccounts",
          "directories"
        ],
        "properties": {
          "apiTokens": {
            "$ref": "#/components/schemas/ApiTokenSetting"
          },
          "directories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DirectoryView"
            },
            "description": "Directories (LDAP with TLS), each checked with a TLS connection now."
          },
          "localAccounts": {
            "$ref": "#/components/schemas/LocalAccountSetting"
          },
          "providers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProviderView"
            }
          }
        }
      },
      "SiteReport": {
        "type": "object",
        "description": "The site this process is connected to, and whether a second site could hold another\ndeployment. One connected site is not a plan.",
        "required": [
          "region",
          "site",
          "sector",
          "members",
          "connectedSites",
          "planned",
          "survival"
        ],
        "properties": {
          "connectedSites": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "members": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "planned": {
            "type": "boolean",
            "description": "A sector in another site was named. The deployment is not started."
          },
          "region": {
            "type": "string"
          },
          "sector": {
            "type": "string"
          },
          "site": {
            "type": "string"
          },
          "survival": {
            "type": "string"
          },
          "warning": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SnapshotItem": {
        "type": "object",
        "required": [
          "name",
          "createdAt"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When Incus took it (RFC 3339)."
          },
          "name": {
            "type": "string"
          }
        }
      },
      "SnapshotList": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SnapshotItem"
            },
            "description": "Oldest first."
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "SnapshotTaken": {
        "type": "object",
        "required": [
          "name",
          "consistency"
        ],
        "properties": {
          "consistency": {
            "type": "string",
            "description": "`crash-consistent` when an instance was running, else `stopped`: a snapshot of a\nrunning database is what a power cut would leave behind."
          },
          "name": {
            "type": "string"
          }
        }
      },
      "Source": {
        "type": "object",
        "description": "Where inventory data came from and when it was read.",
        "required": [
          "provider",
          "observedAt"
        ],
        "properties": {
          "observedAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp (UTC)."
          },
          "provider": {
            "$ref": "#/components/schemas/ProviderMode"
          }
        }
      },
      "StateChange": {
        "type": "object",
        "required": [
          "action"
        ],
        "properties": {
          "action": {
            "$ref": "#/components/schemas/InstanceAction"
          }
        }
      },
      "StepDto": {
        "type": "object",
        "required": [
          "instance",
          "module",
          "state"
        ],
        "properties": {
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "instance": {
            "type": "string"
          },
          "module": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "description": "`pending`, `running`, `succeeded`, `failed` or `skipped`."
          }
        }
      },
      "StorageMemberUsage": {
        "type": "object",
        "description": "One member's share of a pool.",
        "required": [
          "member",
          "usedBytes",
          "totalBytes"
        ],
        "properties": {
          "member": {
            "type": "string"
          },
          "totalBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "usedBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          }
        }
      },
      "StoragePoolReport": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "backupPool": {
            "type": [
              "string",
              "null"
            ]
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoragePoolUsage"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          },
          "volumePool": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "StoragePoolUsage": {
        "type": "object",
        "required": [
          "name",
          "driver",
          "status",
          "description",
          "shared",
          "members",
          "unreadable"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "driver": {
            "type": "string"
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StorageMemberUsage"
            },
            "description": "Use per member as Incus reports it; a shared pool lists the first member that reported it."
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": [
              "string",
              "null"
            ],
            "description": "What Apelora uses it for: `volumes` (`APELORA_VOLUME_POOL`), `backups`\n(`APELORA_BACKUP_POOL`), or nothing."
          },
          "shared": {
            "type": "boolean",
            "description": "One pool every member reaches (clustered LVM, Ceph): its space is counted once."
          },
          "status": {
            "type": "string"
          },
          "total": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/HealthUsage",
                "description": "Used of total over all members (a shared pool once); `None` when no member reported it."
              },
              {
                "type": "null"
              }
            ]
          },
          "unreadable": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Members whose use could not be read, with the reason."
          }
        }
      },
      "StorageVolume": {
        "type": "object",
        "required": [
          "application",
          "module",
          "instance",
          "name",
          "incusName",
          "pool",
          "member",
          "sizeMib",
          "class",
          "usedBy",
          "schedules",
          "backups"
        ],
        "properties": {
          "application": {
            "type": "string"
          },
          "backups": {
            "type": "integer",
            "format": "int64",
            "description": "Backups recorded for it."
          },
          "class": {
            "type": "string"
          },
          "incusName": {
            "type": "string",
            "description": "The Incus volume (`<instance>-<name>`)."
          },
          "instance": {
            "type": "string"
          },
          "lastBackupAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "member": {
            "type": "string"
          },
          "module": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "The design's name (`data`)."
          },
          "pool": {
            "type": "string"
          },
          "schedules": {
            "$ref": "#/components/schemas/VolumeSchedules"
          },
          "sizeMib": {
            "type": "integer",
            "format": "int32"
          },
          "state": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/VolumeUse",
                "description": "What Incus reports now; `None` when Incus could not be read."
              },
              {
                "type": "null"
              }
            ]
          },
          "usedBy": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "StorageVolumeList": {
        "type": "object",
        "required": [
          "source",
          "items"
        ],
        "properties": {
          "backupPool": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where backups go; `None`: backups cannot be taken (`APELORA_BACKUP_POOL` is unset)."
          },
          "incusError": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why Incus could not be read (the list still shows Apelora's records)."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StorageVolume"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "SystemInfo": {
        "type": "object",
        "description": "Facts about this control plane and the Incus release it is pinned to.",
        "required": [
          "version",
          "apiVersion",
          "incusPinned",
          "incusSeries",
          "incusTestedRelease",
          "certificates",
          "incus"
        ],
        "properties": {
          "apiVersion": {
            "type": "string"
          },
          "certificates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CertificateStatus"
            },
            "description": "The certificates Apelora uses to reach Incus and when they expire (empty with the mock)."
          },
          "incus": {
            "$ref": "#/components/schemas/IncusStatus",
            "description": "Incus as observed now: running version, clustering, or why it cannot be reached. (The\npublic `/api/v1/health` says only whether it is reachable.)"
          },
          "incusPinned": {
            "type": "string",
            "description": "Incus release Apelora is tested against (`upstream.lock.yaml`)."
          },
          "incusSeries": {
            "type": "string",
            "description": "Incus LTS series the pin follows, e.g. \"7.0\"."
          },
          "incusTestedRelease": {
            "type": "string",
            "description": "The Incus release this version of Apelora was last tested with, e.g. \"7.0.2\"; empty\nwhen none is recorded."
          },
          "version": {
            "type": "string"
          }
        }
      },
      "TenancyEnvironment": {
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "kind",
          "incusState",
          "incusDetail",
          "effective",
          "apeloraLimits",
          "findings",
          "canSetQuota",
          "canPrepare"
        ],
        "properties": {
          "apeloraLimits": {
            "type": "object",
            "description": "The limit keys Apelora last wrote to the Incus project.",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "canPrepare": {
            "type": "boolean",
            "description": "The caller may create or adopt the Incus project now."
          },
          "canSetQuota": {
            "type": "boolean"
          },
          "checkedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "effective": {
            "$ref": "#/components/schemas/QuotaLimits",
            "description": "The tightest of its own, its project's and its organisation's quota: what Incus gets."
          },
          "findings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenancyFinding"
            }
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "incus": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/TenancyIncusView",
                "description": "As Incus reports it; `None` when the project does not exist or could not be read."
              },
              {
                "type": "null"
              }
            ]
          },
          "incusDetail": {
            "type": "string"
          },
          "incusError": {
            "type": [
              "string",
              "null"
            ]
          },
          "incusProject": {
            "type": [
              "string",
              "null"
            ]
          },
          "incusState": {
            "$ref": "#/components/schemas/TenancyIncusState"
          },
          "kind": {
            "$ref": "#/components/schemas/EnvKind"
          },
          "name": {
            "type": "string"
          },
          "quota": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/QuotaLimits",
                "description": "This environment's own quota."
              },
              {
                "type": "null"
              }
            ]
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "TenancyFinding": {
        "type": "object",
        "description": "Something about an environment's Incus project worth knowing.",
        "required": [
          "severity",
          "message"
        ],
        "properties": {
          "key": {
            "type": [
              "string",
              "null"
            ],
            "description": "The configuration key it is about, if any."
          },
          "message": {
            "type": "string"
          },
          "severity": {
            "$ref": "#/components/schemas/TenancyFindingSeverity"
          }
        }
      },
      "TenancyFindingSeverity": {
        "type": "string",
        "enum": [
          "info",
          "warning",
          "error"
        ]
      },
      "TenancyIncusState": {
        "type": "string",
        "description": "What Apelora knows about an environment's Incus project.",
        "enum": [
          "pending",
          "created",
          "adopted"
        ]
      },
      "TenancyIncusView": {
        "type": "object",
        "description": "What Incus reports for an environment's project.",
        "required": [
          "restrictions",
          "limits",
          "usage"
        ],
        "properties": {
          "limits": {
            "type": "object",
            "description": "`limits.*` keys as set.",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "restrictions": {
            "type": "object",
            "description": "`restricted*` and `features.*` keys as set.",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "usage": {
            "$ref": "#/components/schemas/TenancyProjectUse"
          }
        }
      },
      "TenancyLimitOutcome": {
        "type": "object",
        "description": "What mirroring the quotas did to one environment's Incus project.",
        "required": [
          "environmentId",
          "environment",
          "result",
          "limits",
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string"
          },
          "environment": {
            "type": "string"
          },
          "environmentId": {
            "type": "string",
            "format": "uuid"
          },
          "incusProject": {
            "type": [
              "string",
              "null"
            ]
          },
          "limits": {
            "type": "object",
            "description": "The limit keys asked for (`limits.cpu` = `8`, …).",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "result": {
            "$ref": "#/components/schemas/TenancyLimitResult"
          }
        }
      },
      "TenancyLimitResult": {
        "type": "string",
        "enum": [
          "applied",
          "unchanged",
          "skipped",
          "failed"
        ]
      },
      "TenancyOrganization": {
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "canSetQuota",
          "projects"
        ],
        "properties": {
          "canSetQuota": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenancyProject"
            }
          },
          "quota": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/QuotaLimits"
              },
              {
                "type": "null"
              }
            ]
          },
          "slug": {
            "type": "string"
          },
          "usage": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/QuotaUsage",
                "description": "Use of all its environments; only for callers who see the whole organisation."
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "TenancyOverview": {
        "type": "object",
        "required": [
          "source",
          "adminConfigured",
          "baseline",
          "organizations"
        ],
        "properties": {
          "adminConfigured": {
            "type": "boolean",
            "description": "An admin identity is configured: Apelora can prepare Incus projects and set limits."
          },
          "baseline": {
            "type": "object",
            "description": "The configuration of a project Apelora would create now (restrictions and features).",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "organizations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenancyOrganization"
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "TenancyProject": {
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "canSetQuota",
          "environments"
        ],
        "properties": {
          "canSetQuota": {
            "type": "boolean"
          },
          "environments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenancyEnvironment"
            }
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "quota": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/QuotaLimits"
              },
              {
                "type": "null"
              }
            ]
          },
          "slug": {
            "type": "string"
          },
          "usage": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/QuotaUsage",
                "description": "Use of its environments; `None` when one could not be read."
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "TenancyProjectUse": {
        "type": "object",
        "description": "An Incus project's use and limits (Incus's own aggregate of instance limits, root disk\nsizes and volume sizes).",
        "required": [
          "instances",
          "cpu",
          "memory",
          "disk"
        ],
        "properties": {
          "cpu": {
            "$ref": "#/components/schemas/TenancyResource"
          },
          "disk": {
            "$ref": "#/components/schemas/TenancyResource"
          },
          "instances": {
            "$ref": "#/components/schemas/TenancyResource"
          },
          "memory": {
            "$ref": "#/components/schemas/TenancyResource"
          }
        }
      },
      "TenancyResource": {
        "type": "object",
        "description": "One resource of an Incus project as `GET /1.0/projects/<name>/state` reports it.",
        "required": [
          "used"
        ],
        "properties": {
          "limit": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "`None` when the project has no limit for it."
          },
          "used": {
            "type": "integer",
            "format": "int64",
            "description": "Instances, CPUs or bytes."
          }
        }
      },
      "TokenCreated": {
        "type": "object",
        "required": [
          "token",
          "info"
        ],
        "properties": {
          "info": {
            "$ref": "#/components/schemas/TokenInfo"
          },
          "token": {
            "type": "string",
            "description": "The token itself, shown only in this response."
          }
        }
      },
      "TokenInfo": {
        "type": "object",
        "required": [
          "id",
          "name",
          "role",
          "createdAt"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339."
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "revokedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "role": {
            "$ref": "#/components/schemas/Role"
          }
        }
      },
      "TokenList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TokenInfo"
            }
          }
        }
      },
      "UpdateApplication": {
        "type": "object",
        "properties": {
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "icon": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpgradeCommand": {
        "type": "object",
        "required": [
          "action",
          "confirm"
        ],
        "properties": {
          "action": {
            "type": "string",
            "description": "`start`, `evacuate`, `upgraded`, `restore` or `abandon`."
          },
          "confirm": {
            "type": "string",
            "description": "`upgrade` to start or abandon; the member's name for the other actions."
          },
          "member": {
            "type": "string",
            "description": "The member, for evacuate, upgraded and restore."
          }
        }
      },
      "UpgradeView": {
        "type": "object",
        "description": "What the Upgrades tab shows, whether or not a run has started.",
        "required": [
          "running",
          "order",
          "next",
          "summary"
        ],
        "properties": {
          "member": {
            "type": [
              "string",
              "null"
            ],
            "description": "Whose turn it is, while a run is going."
          },
          "next": {
            "type": "string",
            "description": "`start`, `evacuate`, `upgraded`, `restore` or `none`."
          },
          "order": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Spares, then stand-bys, then voters, the database leader last."
          },
          "running": {
            "type": "boolean"
          },
          "summary": {
            "type": "string"
          }
        }
      },
      "UserDto": {
        "type": "object",
        "required": [
          "id",
          "issuer",
          "createdAt",
          "disabled"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "disabled": {
            "type": "boolean"
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "issuer": {
            "type": "string"
          },
          "lastSeenAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "username": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UserList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UserDto"
            }
          }
        }
      },
      "VersionDocument": {
        "type": "object",
        "required": [
          "document",
          "published"
        ],
        "properties": {
          "document": {
            "type": "object",
            "description": "A Studio document (the application assembly format the Studio imports and exports)."
          },
          "published": {
            "type": "boolean"
          }
        }
      },
      "VersionInfo": {
        "type": "object",
        "required": [
          "revision",
          "published",
          "createdBy",
          "createdAt"
        ],
        "properties": {
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string"
          },
          "draftVersion": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "published": {
            "type": "boolean"
          },
          "revision": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "VersionList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VersionInfo"
            }
          }
        }
      },
      "VolumeBackupItem": {
        "type": "object",
        "required": [
          "name",
          "pool",
          "member",
          "sizeMib",
          "takenAt",
          "scheduled"
        ],
        "properties": {
          "beforeRestore": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The restore job that took it just before overwriting the volume."
          },
          "member": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "The backup's Incus name."
          },
          "pool": {
            "type": "string"
          },
          "present": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "It exists in Incus; `None` when Incus could not be read."
          },
          "scheduled": {
            "type": "boolean",
            "description": "Made by the schedule (pruned to what the schedule keeps), not on request."
          },
          "sizeMib": {
            "type": "integer",
            "format": "int32"
          },
          "takenAt": {
            "type": "string",
            "format": "date-time",
            "description": "When it was taken (RFC 3339): a restore brings back the data as it was then."
          }
        }
      },
      "VolumeBackupList": {
        "type": "object",
        "required": [
          "source",
          "schedules",
          "items"
        ],
        "properties": {
          "backupPool": {
            "type": [
              "string",
              "null"
            ]
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VolumeBackupItem"
            },
            "description": "Oldest first."
          },
          "schedules": {
            "$ref": "#/components/schemas/VolumeSchedules"
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          }
        }
      },
      "VolumeClass": {
        "type": "string",
        "description": "The policy a volume is created under.",
        "enum": [
          "data-local",
          "data-replicated"
        ]
      },
      "VolumeContent": {
        "type": "string",
        "description": "What the volume holds: a mounted filesystem or a raw disk (virtual machines only).",
        "enum": [
          "filesystem",
          "block"
        ]
      },
      "VolumeItem": {
        "type": "object",
        "required": [
          "module",
          "instance",
          "name",
          "incusName",
          "pool",
          "member",
          "sizeMib",
          "content",
          "class",
          "state",
          "usedBy",
          "createdAt"
        ],
        "properties": {
          "class": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "incusName": {
            "type": "string",
            "description": "The Incus volume (`<instance>-<name>`): what to type to delete it."
          },
          "instance": {
            "type": "string"
          },
          "member": {
            "type": "string",
            "description": "Member of a member-local pool; empty on a standalone server."
          },
          "module": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "The design's name (`data`)."
          },
          "pool": {
            "type": "string"
          },
          "sizeMib": {
            "type": "integer",
            "format": "int32"
          },
          "state": {
            "$ref": "#/components/schemas/VolumeUse"
          },
          "usedBy": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Instances using it."
          }
        }
      },
      "VolumeMount": {
        "type": "object",
        "description": "A volume a module asks for.",
        "required": [
          "name",
          "sizeMib"
        ],
        "properties": {
          "class": {
            "$ref": "#/components/schemas/VolumeClass"
          },
          "content": {
            "$ref": "#/components/schemas/VolumeContent"
          },
          "name": {
            "type": "string",
            "description": "Name in the design, e.g. `data`: lowercase letters, digits and `-`, at most 16."
          },
          "path": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where a filesystem volume is mounted inside the instance; none for a block volume."
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "The pool the class resolves to. Set by the control plane, never by a caller."
          },
          "sizeMib": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "VolumeSchedules": {
        "type": "object",
        "properties": {
          "backups": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ScheduleState",
                "description": "`None`: no scheduled backups."
              },
              {
                "type": "null"
              }
            ]
          },
          "snapshots": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ScheduleState",
                "description": "`None`: no scheduled snapshots."
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "VolumeUse": {
        "type": "string",
        "description": "What Incus reports about a recorded volume now.",
        "enum": [
          "attached",
          "retained",
          "missing"
        ]
      },
      "WhoAmI": {
        "type": "object",
        "required": [
          "name",
          "kind",
          "permissions",
          "capabilities",
          "platformPermissions",
          "roles",
          "deployProjects",
          "localAccount",
          "credential"
        ],
        "properties": {
          "capabilities": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Permission ids held at some scope (what the UI may offer; the server decides each request)."
          },
          "credential": {
            "type": "string",
            "description": "The credential this request was made with: `identity-provider` (an OIDC access token),\n`session` (an Apelora session after a password or directory sign-in), `personal-token`,\n`service-token`, `api-token` (legacy) or `development`."
          },
          "deployProjects": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Incus projects this control plane deploys into (`APELORA_DEPLOY_PROJECTS`)."
          },
          "id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The user or service identity id; absent for legacy tokens."
          },
          "kind": {
            "type": "string",
            "description": "`user` (OIDC sign-in), `service` (automation identity), `legacy-token` or `development`."
          },
          "localAccount": {
            "type": "boolean",
            "description": "Signed in with a local account (username and password): may change their password here."
          },
          "name": {
            "type": "string"
          },
          "permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Permission"
            },
            "description": "What the older, coarse permissions amount to for this caller at platform level."
          },
          "platformPermissions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Permission ids held across the whole platform."
          },
          "role": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Role",
                "description": "The role of a legacy API token; `null` for people and service identities."
              },
              {
                "type": "null"
              }
            ]
          },
          "roles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoleGrant"
            },
            "description": "The role assignments in force for this caller."
          }
        }
      }
    },
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "An OIDC access token from the identity provider, an Apelora session (`apu_…`, after a password sign-in), a personal token (`apt_…`), an automation service token (`aps_…`) or a legacy API token (`apl_…`)."
      }
    }
  },
  "security": [
    {
      "bearer": []
    }
  ],
  "tags": [
    {
      "name": "system"
    },
    {
      "name": "inventory"
    },
    {
      "name": "deployment"
    },
    {
      "name": "applications"
    },
    {
      "name": "cluster"
    },
    {
      "name": "administration"
    },
    {
      "name": "audit"
    },
    {
      "name": "identity"
    },
    {
      "name": "sessions"
    },
    {
      "name": "alerts"
    }
  ]
}
