{
 "components": {
  "schemas": {
   "AccessBody": {
    "description": "Internal address published for a console and its protection; both null go back to the discovered address.",
    "properties": {
     "protection": {
      "anyOf": [
       {
        "enum": [
         "native",
         "gateway"
        ],
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Protection",
      "description": "How the console is protected: `native` (its own sign in) or `gateway` (an authenticating gateway in front of it)."
     },
     "published_url": {
      "anyOf": [
       {
        "maxLength": 2048,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Published Url",
      "description": "HTTPS address of the console on the internal network, for example `https://<kafka-ui-host>`."
     }
    },
    "title": "AccessBody",
    "type": "object"
   },
   "AckIn": {
    "properties": {
     "note": {
      "default": "",
      "maxLength": 2000,
      "title": "Note",
      "type": "string",
      "description": "Note kept with the acknowledgement, at most 2000 characters."
     }
    },
    "title": "AckIn",
    "type": "object",
    "description": "Acknowledgement of an alert."
   },
   "ActionBody": {
    "properties": {
     "action": {
      "enum": [
       "start",
       "stop",
       "restart",
       "rolling_restart",
       "service_check",
       "smoke_test",
       "reinstall",
       "configure"
      ],
      "title": "Action",
      "type": "string",
      "description": "Action: `start`, `stop`, `restart`, `rolling_restart`, `service_check`, `smoke_test`, `reinstall` or `configure` (push the current configuration)."
     },
     "approval_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approval Id",
      "description": "Approval granted for this action under `banking-secure`; omit it to use the approval granted to you."
     },
     "batch_size": {
      "default": 1,
      "maximum": 100.0,
      "minimum": 1.0,
      "title": "Batch Size",
      "type": "integer",
      "description": "Hosts handled at the same time by a rolling restart, 1 to 100. Default 1."
     },
     "components": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Components",
      "description": "Components to act on; null: every component."
     },
     "hosts": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Hosts",
      "description": "Host identifiers to act on; null: every host of the service."
     },
     "tolerate_failures": {
      "default": 0,
      "maximum": 100.0,
      "minimum": 0.0,
      "title": "Tolerate Failures",
      "type": "integer",
      "description": "Number of failed hosts accepted before the operation stops, 0 to 100. Default 0."
     }
    },
    "required": [
     "action"
    ],
    "title": "ActionBody",
    "type": "object",
    "description": "An action on a service."
   },
   "ActionIn": {
    "additionalProperties": false,
    "properties": {
     "action": {
      "enum": [
       "start",
       "stop",
       "restart",
       "rolling_restart",
       "scale",
       "maintenance"
      ],
      "title": "Action",
      "type": "string",
      "description": "`start`, `stop`, `restart`, `rolling_restart`, `scale` or `maintenance`."
     },
     "autoscaling": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/AutoscalingIn"
       },
       {
        "type": "null"
       }
      ],
      "description": "For `scale`: autoscaling instead of fixed replicas."
     },
     "enabled": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Enabled",
      "description": "For `maintenance`: true to enter, false to leave."
     },
     "replicas": {
      "anyOf": [
       {
        "maximum": 1000.0,
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Replicas",
      "description": "For `scale`: fixed number of replicas, 0 to 1000."
     }
    },
    "required": [
     "action"
    ],
    "title": "ActionIn",
    "type": "object",
    "description": "An action on a Kubernetes component."
   },
   "AgentIn": {
    "additionalProperties": false,
    "properties": {
     "gateway_url": {
      "maxLength": 512,
      "minLength": 9,
      "title": "Gateway Url",
      "type": "string",
      "description": "HTTPS address of the agent gateway of the Manager, for example `<manager-url>:8461`."
     },
     "offline_after_s": {
      "default": 90,
      "maximum": 3600.0,
      "minimum": 10.0,
      "title": "Offline After S",
      "type": "integer",
      "description": "Seconds without report after which the agent is shown offline, 10 to 3600. Default 90."
     },
     "tenant_id": {
      "default": "default",
      "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
      "title": "Tenant Id",
      "type": "string",
      "description": "Tenant of the agent. Default `default`."
     }
    },
    "required": [
     "gateway_url"
    ],
    "title": "AgentIn",
    "type": "object",
    "description": "Identity of the Navin Cluster Agent to issue."
   },
   "ApprovalBody": {
    "properties": {
     "action": {
      "enum": [
       "service.stop",
       "service.restart",
       "service.rolling_restart",
       "service.reinstall",
       "service.uninstall",
       "service.upgrade",
       "service.rollback",
       "service.restore",
       "backup.restore",
       "config.apply"
      ],
      "title": "Action",
      "type": "string",
      "description": "Action: `service.stop`, `service.restart`, `service.rolling_restart`, `service.reinstall`, `service.uninstall`, `service.upgrade`, `service.rollback`, `service.restore`, `backup.restore` or `config.apply`."
     },
     "reason": {
      "default": "",
      "maxLength": 2000,
      "title": "Reason",
      "type": "string",
      "description": "Why the action is taken. Written to the audit trail with the actor and the time."
     },
     "service": {
      "default": "",
      "maxLength": 80,
      "title": "Service",
      "type": "string",
      "description": "Service the action targets, at most 80 characters."
     }
    },
    "required": [
     "action"
    ],
    "title": "ApprovalBody",
    "type": "object",
    "description": "A request of approval for a disruptive action."
   },
   "ApprovalOnly": {
    "properties": {
     "approval_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approval Id",
      "description": "Identifier of the approved request (four-eyes approval) that authorizes this action."
     }
    },
    "title": "ApprovalOnly",
    "type": "object",
    "description": "Optional approval of a disruptive action."
   },
   "ArtifactIn": {
    "properties": {
     "kind": {
      "default": "archive",
      "title": "Kind",
      "type": "string",
      "description": "Kind of artefact, for example `archive` (default) or `snapshot`."
     },
     "location": {
      "title": "Location",
      "type": "string",
      "description": "Path of the encrypted backup file, readable by the Manager (filesystem target)."
     },
     "verification_inventory": {
      "additionalProperties": {
       "additionalProperties": true,
       "type": "object"
      },
      "title": "Verification Inventory",
      "type": "object",
      "description": "For a `pg_dump` (custom format) only: rows and SHA-256 of every table of the backed up database, `{\"schema.table\": {\"rows\": 50, \"sha256\": \"...\"}}`, computed when the dump is taken. A restore is executed only for an artefact with this inventory and is verified against it."
     },
     "versions": {
      "additionalProperties": {
       "type": "string"
      },
      "default": {},
      "title": "Versions",
      "type": "object",
      "description": "Versions of the backed up components. A pg_dump requires the key `postgres`, for example `{\"postgres\": \"16.4\"}`; used by the restore compatibility check."
     }
    },
    "required": [
     "location"
    ],
    "title": "ArtifactIn",
    "type": "object",
    "description": "A backup artefact to record."
   },
   "AutoscalingIn": {
    "additionalProperties": false,
    "properties": {
     "engine": {
      "default": "Auto",
      "enum": [
       "Auto",
       "HPA",
       "KEDA"
      ],
      "title": "Engine",
      "type": "string",
      "description": "`Auto` (default), `HPA` or `KEDA`."
     },
     "max_replicas": {
      "maximum": 1000.0,
      "minimum": 1.0,
      "title": "Max Replicas",
      "type": "integer",
      "description": "Largest number of replicas, 1 to 1000, not below `min_replicas`."
     },
     "min_replicas": {
      "maximum": 1000.0,
      "minimum": 1.0,
      "title": "Min Replicas",
      "type": "integer",
      "description": "Smallest number of replicas, 1 to 1000."
     },
     "target": {
      "anyOf": [
       {
        "maxLength": 253,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Target",
      "description": "Target of the autoscaling, passed to the operator when set, at most 253 characters."
     },
     "target_cpu_utilization_percentage": {
      "maximum": 1000.0,
      "minimum": 1.0,
      "title": "Target Cpu Utilization Percentage",
      "type": "integer",
      "description": "Target CPU use in percent of the requests, 1 to 1000."
     }
    },
    "required": [
     "min_replicas",
     "max_replicas",
     "target_cpu_utilization_percentage"
    ],
    "title": "AutoscalingIn",
    "type": "object",
    "description": "Autoscaling of a Kubernetes component."
   },
   "BackupBody": {
    "properties": {
     "services": {
      "items": {
       "type": "string"
      },
      "maxItems": 100,
      "title": "Services",
      "type": "array",
      "description": "Services to back up, at most 100; empty: every backupable service."
     }
    },
    "title": "BackupBody",
    "type": "object",
    "description": "Services of a coordinated backup."
   },
   "BootstrapIn": {
    "additionalProperties": false,
    "properties": {
     "certificate": {
      "anyOf": [
       {
        "maxLength": 20000,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Certificate",
      "description": "OpenSSH user certificate of the key, signed by an approved CA, instead of an authorized key."
     },
     "cluster_id": {
      "title": "Cluster Id",
      "type": "string",
      "description": "Cluster the host joins."
     },
     "fqdn": {
      "anyOf": [
       {
        "maxLength": 253,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Fqdn",
      "description": "FQDN passed to the registration of the agent; optional."
     },
     "jumps": {
      "items": {
       "$ref": "#/components/schemas/EndpointIn"
      },
      "maxItems": 4,
      "title": "Jumps",
      "type": "array",
      "description": "Jump hosts to go through, in order, at most 4."
     },
     "private_key": {
      "maxLength": 20000,
      "minLength": 20,
      "title": "Private Key",
      "type": "string",
      "description": "Private SSH key of the operator (OpenSSH or PEM). Kept in memory for the run only, never stored."
     },
     "ssh_user": {
      "anyOf": [
       {
        "maxLength": 32,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Ssh User",
      "description": "SSH account; default: the bootstrap user of the SSH policy."
     },
     "target": {
      "$ref": "#/components/schemas/EndpointIn",
      "description": "The host to bootstrap."
     },
     "use_sudo": {
      "default": true,
      "title": "Use Sudo",
      "type": "boolean",
      "description": "Run the privileged steps with the sudo allowlist. Default true."
     }
    },
    "required": [
     "cluster_id",
     "target",
     "private_key"
    ],
    "title": "BootstrapIn",
    "type": "object",
    "description": "SSH access for the bootstrap of a node agent. A password field is refused."
   },
   "BreakGlassIn": {
    "additionalProperties": false,
    "properties": {
     "principal": {
      "default": "navin-breakglass",
      "maxLength": 32,
      "minLength": 1,
      "title": "Principal",
      "type": "string",
      "description": "Unix account of the certificate. Default `navin-breakglass`."
     },
     "public_key": {
      "maxLength": 2000,
      "minLength": 20,
      "title": "Public Key",
      "type": "string",
      "description": "OpenSSH public key of the requester, the one the certificate will sign."
     },
     "reason": {
      "maxLength": 1000,
      "minLength": 10,
      "title": "Reason",
      "type": "string",
      "description": "Why the emergency access is needed, 10 to 1000 characters."
     },
     "ttl_s": {
      "default": 1800,
      "maximum": 14400.0,
      "minimum": 60.0,
      "title": "Ttl S",
      "type": "integer",
      "description": "Validity of the certificate in seconds, 60 to 14400 (4 hours). Default 1800."
     }
    },
    "required": [
     "reason",
     "public_key"
    ],
    "title": "BreakGlassIn",
    "type": "object",
    "description": "An emergency SSH access request."
   },
   "ChecksumsIn": {
    "additionalProperties": false,
    "description": "Checksum lines of the release.",
    "properties": {
     "text": {
      "maxLength": 65536,
      "minLength": 1,
      "title": "Text",
      "type": "string",
      "description": "Lines `<sha256>  <filename>` of the SHA256SUMS and .sha256 files of the release, pasted together (64 KiB at most); lines naming an unknown file are ignored."
     }
    },
    "required": [
     "text"
    ],
    "title": "ChecksumsIn",
    "type": "object"
   },
   "ClientCertificate": {
    "additionalProperties": false,
    "description": "Client certificate for mutual TLS, PEM; an empty object removes it on an update.",
    "properties": {
     "client_cert": {
      "anyOf": [
       {
        "maxLength": 65536,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Client Cert",
      "description": "Client certificate, PEM encoded."
     },
     "client_key": {
      "anyOf": [
       {
        "maxLength": 65536,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Client Key",
      "description": "Private key of the client certificate, PEM encoded. Write only, sealed at rest."
     }
    },
    "title": "ClientCertificate",
    "type": "object"
   },
   "ClusterActionBody": {
    "properties": {
     "action": {
      "enum": [
       "start",
       "stop",
       "restart",
       "rolling_restart",
       "restart_stale",
       "service_check"
      ],
      "title": "Action",
      "type": "string",
      "description": "Action: `start`, `stop`, `restart` (stop of every service in reverse order, then start in order), `rolling_restart`, `restart_stale` (only the instances whose configuration changed) or `service_check`."
     },
     "approval_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approval Id",
      "description": "Approval granted for the service `*` under `banking-secure`; omit it to use the approval granted to you."
     },
     "batch_size": {
      "default": 1,
      "maximum": 100.0,
      "minimum": 1.0,
      "title": "Batch Size",
      "type": "integer",
      "description": "Hosts restarted at the same time by `rolling_restart` and `restart_stale`, 1 to 100. Default 1."
     },
     "dry_run": {
      "default": false,
      "title": "Dry Run",
      "type": "boolean",
      "description": "Return the plan (services in order, left out instances, stages) without creating the operation. Default false."
     },
     "hosts": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "maxItems": 1000,
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Hosts",
      "description": "Host identifiers to act on, at most 1000; null: every host."
     },
     "services": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "maxItems": 200,
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Services",
      "description": "Services to act on, at most 200; null: every managed service of the cluster."
     },
     "tolerate_failures": {
      "default": 0,
      "maximum": 100.0,
      "minimum": 0.0,
      "title": "Tolerate Failures",
      "type": "integer",
      "description": "Failed hosts accepted in a batch before the operation stops, 0 to 100. Default 0."
     }
    },
    "required": [
     "action"
    ],
    "title": "ClusterActionBody",
    "type": "object",
    "description": "An action on every managed service of a cluster, in dependency order."
   },
   "ClusterIn": {
    "properties": {
     "description": {
      "default": "",
      "title": "Description",
      "type": "string",
      "description": "Free text describing the cluster. Default empty."
     },
     "mode": {
      "default": "production",
      "enum": [
       "production",
       "preprod",
       "test",
       "development",
       "sandbox"
      ],
      "title": "Mode",
      "type": "string",
      "description": "Kind of environment: `production` (default), `preprod`, `test`, `development` or `sandbox`. Cannot be changed later."
     },
     "name": {
      "maxLength": 80,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Unique name of the cluster, 1 to 80 characters."
     },
     "profile": {
      "anyOf": [
       {
        "enum": [
         "development",
         "standard",
         "banking-secure",
         "air-gapped",
         "hybrid"
        ],
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Profile",
      "description": "Installation profile: `development`, `standard`, `banking-secure`, `air-gapped` or `hybrid`. Default: `standard` for `production` and `preprod`, else `development`."
     }
    },
    "required": [
     "name"
    ],
    "title": "ClusterIn",
    "type": "object",
    "description": "A new cluster."
   },
   "ClusterPatch": {
    "properties": {
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description",
      "description": "New description."
     },
     "name": {
      "anyOf": [
       {
        "maxLength": 80,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name",
      "description": "New unique name, 1 to 80 characters."
     },
     "profile": {
      "anyOf": [
       {
        "enum": [
         "development",
         "standard",
         "banking-secure",
         "air-gapped",
         "hybrid"
        ],
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Profile",
      "description": "New installation profile: `development`, `standard`, `banking-secure`, `air-gapped` or `hybrid`."
     }
    },
    "title": "ClusterPatch",
    "type": "object",
    "description": "Change of a cluster; a field left out or null is kept."
   },
   "CommandBody": {
    "properties": {
     "host_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Host Id",
      "description": "Host to run the command on; null: the host chosen by the command definition."
     },
     "params": {
      "additionalProperties": true,
      "title": "Params",
      "type": "object",
      "description": "Values of the parameters declared by the command, checked against their types."
     }
    },
    "title": "CommandBody",
    "type": "object",
    "description": "Parameters of a custom command."
   },
   "CompleteIn": {
    "properties": {
     "evidence": {
      "additionalProperties": true,
      "title": "Evidence",
      "type": "object",
      "description": "Evidence of the measures (logs, timestamps, screenshots references...)."
     },
     "ok": {
      "title": "Ok",
      "type": "boolean",
      "description": "Whether the exercise succeeded."
     },
     "rpo_observed_seconds": {
      "minimum": 0.0,
      "title": "Rpo Observed Seconds",
      "type": "number",
      "description": "Data loss observed, in seconds (0 or more)."
     },
     "rto_observed_seconds": {
      "minimum": 0.0,
      "title": "Rto Observed Seconds",
      "type": "number",
      "description": "Time to restore the service observed, in seconds (0 or more)."
     }
    },
    "required": [
     "rpo_observed_seconds",
     "rto_observed_seconds",
     "ok",
     "evidence"
    ],
    "title": "CompleteIn",
    "type": "object",
    "description": "Measures of a completed exercise or failover."
   },
   "ComponentBody": {
    "properties": {
     "component": {
      "title": "Component",
      "type": "string",
      "description": "Name of the component."
     },
     "ha_acknowledged": {
      "default": false,
      "title": "Ha Acknowledged",
      "type": "boolean",
      "description": "Accept a topology below the high availability requirements. Default false."
     },
     "hosts": {
      "items": {
       "type": "string"
      },
      "maxItems": 500,
      "minItems": 1,
      "title": "Hosts",
      "type": "array",
      "description": "Identifiers of the hosts to place it on, 1 to 500."
     }
    },
    "required": [
     "component",
     "hosts"
    ],
    "title": "ComponentBody",
    "type": "object",
    "description": "Instances of a component to add."
   },
   "ComponentIn": {
    "additionalProperties": false,
    "properties": {
     "autoscaling": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/AutoscalingIn"
       },
       {
        "type": "null"
       }
      ],
      "description": "Autoscaling instead of fixed replicas."
     },
     "desired_state": {
      "default": "started",
      "enum": [
       "started",
       "stopped"
      ],
      "title": "Desired State",
      "type": "string",
      "description": "`started` (default) or `stopped`."
     },
     "maintenance": {
      "default": false,
      "title": "Maintenance",
      "type": "boolean",
      "description": "Create it in maintenance. Default false."
     },
     "name": {
      "anyOf": [
       {
        "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name",
      "description": "Name of the resource (DNS label); default: the service name."
     },
     "pdb": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/PdbIn"
       },
       {
        "type": "null"
       }
      ],
      "description": "Pod disruption budget."
     },
     "replicas": {
      "anyOf": [
       {
        "maximum": 1000.0,
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Replicas",
      "description": "Fixed number of replicas, 0 to 1000; never below the `min_available` of the budget."
     },
     "secret_refs": {
      "items": {
       "$ref": "#/components/schemas/SecretRefIn"
      },
      "maxItems": 32,
      "title": "Secret Refs",
      "type": "array",
      "description": "Values taken from Kubernetes Secrets, at most 32."
     },
     "service": {
      "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
      "title": "Service",
      "type": "string",
      "description": "Name of the catalog service."
     },
     "source": {
      "$ref": "#/components/schemas/Source",
      "description": "Where the chart comes from."
     },
     "values": {
      "additionalProperties": true,
      "title": "Values",
      "type": "object",
      "description": "Chart values; must not contain secrets."
     },
     "version": {
      "anyOf": [
       {
        "maxLength": 64,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Version",
      "description": "Version of the service; default: the catalog version."
     }
    },
    "required": [
     "service",
     "source"
    ],
    "title": "ComponentIn",
    "type": "object",
    "description": "A catalog service to run on Kubernetes."
   },
   "ComponentPatch": {
    "additionalProperties": false,
    "properties": {
     "pdb": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/PdbIn"
       },
       {
        "type": "null"
       }
      ],
      "description": "New pod disruption budget."
     },
     "remove_pdb": {
      "default": false,
      "title": "Remove Pdb",
      "type": "boolean",
      "description": "Remove the disruption budget. Default false."
     },
     "secret_refs": {
      "anyOf": [
       {
        "items": {
         "$ref": "#/components/schemas/SecretRefIn"
        },
        "maxItems": 32,
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Secret Refs",
      "description": "New secret references, replacing the current ones."
     },
     "source": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/Source"
       },
       {
        "type": "null"
       }
      ],
      "description": "New chart source."
     },
     "values": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Values",
      "description": "New chart values, replacing the current ones; no secret."
     },
     "version": {
      "anyOf": [
       {
        "maxLength": 64,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Version",
      "description": "New version of the service."
     }
    },
    "title": "ComponentPatch",
    "type": "object",
    "description": "Change of a Kubernetes component; a field left out is kept."
   },
   "ConfigBody": {
    "properties": {
     "note": {
      "default": "",
      "maxLength": 2000,
      "title": "Note",
      "type": "string",
      "description": "Why the configuration changes, kept with the version, at most 2000 characters."
     },
     "properties": {
      "additionalProperties": true,
      "title": "Properties",
      "type": "object",
      "description": "Parameters to change as `{name: value}`; others are kept. A secret sent back as `{\"secret\": true, \"set\": true}` is kept, `null` removes a value."
     }
    },
    "required": [
     "properties"
    ],
    "title": "ConfigBody",
    "type": "object",
    "description": "A change of the configuration of a service."
   },
   "ConnectAuth": {
    "additionalProperties": false,
    "description": "Authentication method among those the descriptor offers (`connect.auth`) and its fields; secret fields are never echoed. Without a method the stored one is kept on an update, else `none` when offered.",
    "properties": {
     "fields": {
      "additionalProperties": {
       "type": "string"
      },
      "maxProperties": 16,
      "title": "Fields",
      "type": "object",
      "description": "Fields of the method, for example `username` and `password`, at most 16. A secret field left empty keeps the stored value on an update."
     },
     "method": {
      "anyOf": [
       {
        "maxLength": 40,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Method",
      "description": "Name of the method, for example `basic`, `token` or `none`."
     }
    },
    "title": "ConnectAuth",
    "type": "object"
   },
   "ConnectBody": {
    "description": "Configure & Connect: an existing service registered against the `connect` section of its descriptor.",
    "properties": {
     "auth": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/ConnectAuth"
       },
       {
        "type": "null"
       }
      ],
      "description": "Authentication method and its fields."
     },
     "ca_pem": {
      "anyOf": [
       {
        "maxLength": 65536,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Ca Pem",
      "description": "Certificate authority (PEM) that signed the certificate of the service."
     },
     "config": {
      "additionalProperties": true,
      "maxProperties": 100,
      "title": "Config",
      "type": "object",
      "description": "Values of the configuration keys of the connect descriptor, at most 100."
     },
     "credentials_ref": {
      "anyOf": [
       {
        "maxLength": 512,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Credentials Ref",
      "description": "Reference to credentials held elsewhere, as a URI such as `vault://kv/navin/postgres`."
     },
     "endpoint": {
      "maxLength": 2048,
      "minLength": 1,
      "title": "Endpoint",
      "type": "string",
      "description": "Address of the service, for example `https://<search-host>:9200`."
     },
     "mtls": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/ClientCertificate"
       },
       {
        "type": "null"
       }
      ],
      "description": "Client certificate for mutual TLS."
     },
     "name": {
      "maxLength": 64,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Name of the catalog service to connect, for example `opensearch`."
     },
     "tls_verify": {
      "default": true,
      "title": "Tls Verify",
      "type": "boolean",
      "description": "Verify the TLS certificate of the service. Default true; required in production."
     }
    },
    "required": [
     "name",
     "endpoint"
    ],
    "title": "ConnectBody",
    "type": "object"
   },
   "ConnectionCreate": {
    "additionalProperties": false,
    "properties": {
     "description": {
      "default": "",
      "maxLength": 1000,
      "title": "Description",
      "type": "string",
      "description": "Free text, at most 1000 characters."
     },
     "name": {
      "maxLength": 100,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Unique name, 1 to 100 characters."
     },
     "params": {
      "additionalProperties": true,
      "title": "Params",
      "type": "object",
      "description": "Parameters of the type, for example `host`, `port`, `database`, `username`, `sslmode` for `postgresql`."
     },
     "secret": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Secret",
      "description": "Secret of the connection (password, token or key). Write only, sealed at rest."
     },
     "type": {
      "pattern": "^(clickhouse|elasticsearch|http|kafka|ldap|mysql|nats|oidc|opensearch|postgresql|qdrant|redis|s3|smtp|syslog)$",
      "title": "Type",
      "type": "string",
      "description": "Type: `clickhouse`, `elasticsearch`, `http`, `kafka`, `ldap`, `mysql`, `nats`, `oidc`, `opensearch`, `postgresql`, `qdrant`, `redis`, `s3`, `smtp` or `syslog`."
     }
    },
    "required": [
     "name",
     "type"
    ],
    "title": "ConnectionCreate",
    "type": "object",
    "description": "A new external connection."
   },
   "ConnectionValidate": {
    "additionalProperties": false,
    "properties": {
     "params": {
      "additionalProperties": true,
      "title": "Params",
      "type": "object",
      "description": "Parameters of the type."
     },
     "secret": {
      "anyOf": [
       {
        "maxLength": 4096,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Secret",
      "description": "Secret to test with, at most 4096 characters. Never stored."
     },
     "type": {
      "pattern": "^(clickhouse|elasticsearch|http|kafka|ldap|mysql|nats|oidc|opensearch|postgresql|qdrant|redis|s3|smtp|syslog)$",
      "title": "Type",
      "type": "string",
      "description": "Type of the connection, as for a creation."
     }
    },
    "required": [
     "type"
    ],
    "title": "ConnectionValidate",
    "type": "object",
    "description": "A connection to test without saving it."
   },
   "ConsistencyIn": {
    "properties": {
     "reconcile": {
      "default": false,
      "title": "Reconcile",
      "type": "boolean",
      "description": "Mark missing rows and quarantine orphan objects. Default false (report only)."
     },
     "registry": {
      "default": [],
      "items": {
       "type": "string"
      },
      "title": "Registry",
      "type": "array",
      "description": "SHA-256 digests the artefact registry declares as backed up."
     },
     "target_id": {
      "title": "Target Id",
      "type": "string",
      "description": "Identifier of the backup target."
     }
    },
    "required": [
     "target_id"
    ],
    "title": "ConsistencyIn",
    "type": "object",
    "description": "A consistency check of a filesystem backup target."
   },
   "DecisionBody": {
    "properties": {
     "decision": {
      "enum": [
       "approve",
       "reject"
      ],
      "title": "Decision",
      "type": "string",
      "description": "`approve` or `reject`."
     }
    },
    "required": [
     "decision"
    ],
    "title": "DecisionBody",
    "type": "object",
    "description": "Decision on an approval request."
   },
   "DefinitionPatch": {
    "properties": {
     "critical": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Critical",
      "description": "Threshold of the `critical` state, in the unit of the definition (percent, seconds, days...)."
     },
     "enabled": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Enabled",
      "description": "Whether the definition is evaluated."
     },
     "interval_s": {
      "anyOf": [
       {
        "maximum": 86400.0,
        "minimum": 10.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Interval S",
      "description": "Evaluation interval in seconds, 10 to 86400."
     },
     "warning": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Warning",
      "description": "Threshold of the `warning` state, in the unit of the definition."
     }
    },
    "title": "DefinitionPatch",
    "type": "object",
    "description": "Change of an alert definition; a field left out or null is kept."
   },
   "DiscoverIn": {
    "additionalProperties": false,
    "description": "The proxy to read.",
    "properties": {
     "auth_mode": {
      "default": "user_key",
      "enum": [
       "user_key",
       "shared_key",
       "none"
      ],
      "title": "Auth Mode",
      "type": "string",
      "description": "`user_key`, `shared_key` or `none`."
     },
     "base_url": {
      "default": "",
      "maxLength": 2048,
      "title": "Base Url",
      "type": "string",
      "description": "Address of the proxy, with or without `/v1`."
     },
     "ca_pem": {
      "default": "",
      "maxLength": 65536,
      "title": "Ca Pem",
      "type": "string",
      "description": "PEM of an internal CA the Manager trusts for this call."
     },
     "headers": {
      "additionalProperties": {
       "maxLength": 4096,
       "type": "string"
      },
      "maxProperties": 50,
      "title": "Headers",
      "type": "object",
      "description": "Extra HTTP headers."
     },
     "key": {
      "default": "",
      "maxLength": 8192,
      "title": "Key",
      "type": "string",
      "description": "Key typed for this call only, never stored nor audited."
     },
     "litellm_cluster_id": {
      "anyOf": [
       {
        "format": "uuid",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Litellm Cluster Id",
      "description": "Cluster of a LiteLLM service installed by the Manager: it is then read with its master key and the CA of the Manager, both kept in the server; requires `litellm_service`."
     },
     "litellm_service": {
      "default": "",
      "maxLength": 100,
      "title": "Litellm Service",
      "type": "string",
      "description": "Name of the installed LiteLLM service; requires `litellm_cluster_id`."
     },
     "shared_key_ref": {
      "anyOf": [
       {
        "format": "uuid",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Shared Key Ref",
      "description": "Vault entry of the shared key."
     }
    },
    "title": "DiscoverIn",
    "type": "object"
   },
   "DrPlanIn": {
    "properties": {
     "mode": {
      "title": "Mode",
      "type": "string",
      "description": "DR mode: `active_passive`, `warm`, `cold` or `active_active_stateless`."
     },
     "name": {
      "maxLength": 100,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Name of the plan, 1 to 100 characters."
     },
     "primary_site": {
      "title": "Primary Site",
      "type": "string",
      "description": "Name of the primary site; created when unknown."
     },
     "rpo_target_seconds": {
      "anyOf": [
       {
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Rpo Target Seconds",
      "description": "Recovery point objective: the largest loss of data accepted, in seconds."
     },
     "rto_target_seconds": {
      "anyOf": [
       {
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Rto Target Seconds",
      "description": "Recovery time objective: the longest time accepted to restore the service, in seconds."
     },
     "secondary_site": {
      "title": "Secondary Site",
      "type": "string",
      "description": "Name of the secondary site; must differ from the primary."
     },
     "sequence": {
      "default": [],
      "items": {
       "additionalProperties": true,
       "type": "object"
      },
      "title": "Sequence",
      "type": "array",
      "description": "Ordered steps of the failover, as free objects."
     }
    },
    "required": [
     "name",
     "mode",
     "primary_site",
     "secondary_site"
    ],
    "title": "DrPlanIn",
    "type": "object",
    "description": "A new disaster recovery plan."
   },
   "EndpointIn": {
    "additionalProperties": false,
    "properties": {
     "host": {
      "maxLength": 253,
      "minLength": 1,
      "title": "Host",
      "type": "string",
      "description": "Host name or address, for example `<node1-host>`."
     },
     "host_ca": {
      "default": "",
      "maxLength": 2000,
      "title": "Host Ca",
      "type": "string",
      "description": "SSH host CA public key that signs the host key, instead of `host_key`."
     },
     "host_key": {
      "default": "",
      "maxLength": 2000,
      "title": "Host Key",
      "type": "string",
      "description": "Expected SSH host public key (known hosts line); the connection is refused when it differs."
     },
     "port": {
      "default": 22,
      "maximum": 65535.0,
      "minimum": 1.0,
      "title": "Port",
      "type": "integer",
      "description": "SSH port, 1 to 65535. Default 22."
     },
     "user": {
      "default": "",
      "maxLength": 32,
      "title": "User",
      "type": "string",
      "description": "Account on this endpoint; empty: the SSH user of the request."
     }
    },
    "required": [
     "host"
    ],
    "title": "EndpointIn",
    "type": "object",
    "description": "An SSH endpoint: the target or a jump host."
   },
   "EnrollConfirmBody": {
    "additionalProperties": false,
    "properties": {
     "code": {
      "maxLength": 20,
      "minLength": 1,
      "title": "Code",
      "type": "string",
      "description": "Current code (6 digits) of the new secret in the authenticator application."
     },
     "mfa_token": {
      "maxLength": 200,
      "minLength": 1,
      "title": "Mfa Token",
      "type": "string",
      "description": "Challenge token returned by the login (`mfa_token`), valid 5 minutes."
     }
    },
    "required": [
     "mfa_token",
     "code"
    ],
    "title": "EnrollConfirmBody",
    "type": "object",
    "description": "Confirmation of the enrollment required at sign in."
   },
   "EnrollStartBody": {
    "additionalProperties": false,
    "properties": {
     "mfa_token": {
      "maxLength": 200,
      "minLength": 1,
      "title": "Mfa Token",
      "type": "string",
      "description": "Challenge token returned by the login (`mfa_token`), valid 5 minutes."
     }
    },
    "required": [
     "mfa_token"
    ],
    "title": "EnrollStartBody",
    "type": "object",
    "description": "Start of the enrollment required at sign in."
   },
   "EntryIn": {
    "additionalProperties": false,
    "description": "A service of the vault: name, URL, login, password and API key or secret key (the last four optional).",
    "properties": {
     "api_key": {
      "default": "",
      "maxLength": 8192,
      "title": "Api Key",
      "type": "string",
      "description": "API key or secret key, at most 8192 characters. Write only, sealed."
     },
     "login": {
      "default": "",
      "maxLength": 320,
      "title": "Login",
      "type": "string",
      "description": "Login of the account, at most 320 characters."
     },
     "name": {
      "maxLength": 120,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Unique name of the service, 1 to 120 characters, stored in clear."
     },
     "password": {
      "default": "",
      "maxLength": 4096,
      "title": "Password",
      "type": "string",
      "description": "Password of the account, at most 4096 characters. Write only, sealed."
     },
     "url": {
      "default": "",
      "maxLength": 2048,
      "title": "Url",
      "type": "string",
      "description": "Address of the service, for example `https://<grafana-host>`."
     }
    },
    "required": [
     "name"
    ],
    "title": "EntryIn",
    "type": "object"
   },
   "EntryPatch": {
    "additionalProperties": false,
    "description": "Fields to change; an omitted field is kept, an empty password or key clears it.",
    "properties": {
     "api_key": {
      "anyOf": [
       {
        "maxLength": 8192,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Api Key",
      "description": "New API key or secret key; an empty string clears it."
     },
     "login": {
      "anyOf": [
       {
        "maxLength": 320,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Login",
      "description": "New login."
     },
     "name": {
      "anyOf": [
       {
        "maxLength": 120,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name",
      "description": "New unique name."
     },
     "password": {
      "anyOf": [
       {
        "maxLength": 4096,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Password",
      "description": "New password; an empty string clears it."
     },
     "url": {
      "anyOf": [
       {
        "maxLength": 2048,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Url",
      "description": "New address."
     }
    },
    "title": "EntryPatch",
    "type": "object"
   },
   "EvidenceIn": {
    "properties": {
     "digest": {
      "anyOf": [
       {
        "maxLength": 100,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Digest",
      "description": "SHA-256 of the evidence (commands, recording), at most 100 characters."
     },
     "kind": {
      "enum": [
       "session_start",
       "command",
       "session_end",
       "recording"
      ],
      "title": "Kind",
      "type": "string",
      "description": "`session_start`, `command`, `session_end` or `recording`."
     },
     "summary": {
      "default": "",
      "maxLength": 2000,
      "title": "Summary",
      "type": "string",
      "description": "Short description, redacted before it is stored, at most 2000 characters."
     }
    },
    "required": [
     "kind"
    ],
    "title": "EvidenceIn",
    "type": "object",
    "description": "Evidence of a break glass session."
   },
   "ExerciseIn": {
    "properties": {
     "plan_id": {
      "title": "Plan Id",
      "type": "string",
      "description": "Identifier of the DR plan."
     }
    },
    "required": [
     "plan_id"
    ],
    "title": "ExerciseIn",
    "type": "object",
    "description": "An exercise or failover request."
   },
   "FetchIn": {
    "additionalProperties": false,
    "description": "The vault entry holding the GitHub token of a fetch.",
    "properties": {
     "vault_entry_id": {
      "format": "uuid",
      "title": "Vault Entry Id",
      "type": "string",
      "description": "Vault entry whose API key is a GitHub token allowed to read the release; the token never leaves the server."
     }
    },
    "required": [
     "vault_entry_id"
    ],
    "title": "FetchIn",
    "type": "object"
   },
   "GroupBody": {
    "properties": {
     "hosts": {
      "items": {
       "type": "string"
      },
      "maxItems": 1000,
      "title": "Hosts",
      "type": "array",
      "description": "Identifiers of the hosts of the group, at most 1000; each must run the service and belong to no other group."
     },
     "name": {
      "maxLength": 120,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Unique name of the group within the service, 1 to 120 characters."
     },
     "overrides": {
      "additionalProperties": true,
      "title": "Overrides",
      "type": "object",
      "description": "Parameters overridden on these hosts as `{name: value}`."
     }
    },
    "required": [
     "name"
    ],
    "title": "GroupBody",
    "type": "object",
    "description": "A config group: values overridden on some hosts."
   },
   "GroupIn": {
    "properties": {
     "cluster_id": {
      "title": "Cluster Id",
      "type": "string",
      "description": "Cluster of the group."
     },
     "component": {
      "maxLength": 80,
      "minLength": 1,
      "title": "Component",
      "type": "string",
      "description": "Name of the component the group keeps available, 1 to 80 characters."
     },
     "deployment_mode": {
      "default": "NODE_GROUP",
      "enum": [
       "SINGLE_HOST",
       "NODE_GROUP",
       "K8S_EXISTING",
       "K8S_MANAGED",
       "MULTI_CLUSTER",
       "EXTERNAL_MANAGED"
      ],
      "title": "Deployment Mode",
      "type": "string",
      "description": "Where it runs: `SINGLE_HOST`, `NODE_GROUP` (default), `K8S_EXISTING`, `K8S_MANAGED`, `MULTI_CLUSTER` or `EXTERNAL_MANAGED`."
     },
     "desired_replicas": {
      "maximum": 99.0,
      "minimum": 1.0,
      "title": "Desired Replicas",
      "type": "integer",
      "description": "Number of replicas wanted, 1 to 99; at least 2 for `ha`, 3 for `critical-ha`."
     },
     "failover_policy": {
      "$ref": "#/components/schemas/PolicyIn",
      "description": "How a failover happens."
     },
     "fault_domains": {
      "items": {
       "type": "string"
      },
      "title": "Fault Domains",
      "type": "array",
      "description": "Distinct fault domains (racks, zones) of the group; at least 2 for `ha`, 3 for `critical-ha`."
     },
     "ha_mode": {
      "enum": [
       "single",
       "active_passive",
       "active_active",
       "quorum"
      ],
      "title": "Ha Mode",
      "type": "string",
      "description": "HA mode: `single`, `active_passive`, `active_active` or `quorum`."
     },
     "members": {
      "items": {
       "$ref": "#/components/schemas/MemberIn"
      },
      "title": "Members",
      "type": "array",
      "description": "Members of the group."
     },
     "name": {
      "maxLength": 80,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Name of the group, 1 to 80 characters."
     },
     "ownership_mode": {
      "default": "PLATFORM_MANAGED",
      "enum": [
       "PLATFORM_MANAGED",
       "CLIENT_MANAGED"
      ],
      "title": "Ownership Mode",
      "type": "string",
      "description": "Who runs it: `PLATFORM_MANAGED` (default, the Manager acts on it) or `CLIENT_MANAGED` (the Manager only observes)."
     },
     "profile": {
      "enum": [
       "standalone",
       "ha",
       "critical-ha"
      ],
      "title": "Profile",
      "type": "string",
      "description": "Availability profile: `standalone`, `ha` or `critical-ha`."
     },
     "rpo_target_seconds": {
      "anyOf": [
       {
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Rpo Target Seconds",
      "description": "Recovery point objective: the largest loss of data accepted, in seconds."
     },
     "rto_target_seconds": {
      "anyOf": [
       {
        "exclusiveMinimum": 0.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Rto Target Seconds",
      "description": "Recovery time objective: the longest time accepted to restore the service, in seconds (more than 0)."
     }
    },
    "required": [
     "cluster_id",
     "name",
     "component",
     "ha_mode",
     "profile",
     "desired_replicas"
    ],
    "title": "GroupIn",
    "type": "object",
    "description": "A new high availability group."
   },
   "HTTPValidationError": {
    "properties": {
     "detail": {
      "items": {
       "$ref": "#/components/schemas/ValidationError"
      },
      "title": "Detail",
      "type": "array",
      "description": "Invalid items of the request, one per field."
     }
    },
    "title": "HTTPValidationError",
    "type": "object",
    "description": "Validation error shape declared by FastAPI. The Manager actually answers an invalid request with `422` and the error envelope of the API, code `validation_error`, whose `details.fields` lists the invalid fields."
   },
   "HostActionBody": {
    "properties": {
     "action": {
      "enum": [
       "start",
       "stop",
       "restart",
       "configure",
       "reinstall"
      ],
      "title": "Action",
      "type": "string",
      "description": "Action: `start`, `stop`, `restart`, `configure` or `reinstall`."
     },
     "approval_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approval Id",
      "description": "Approval granted for this action under `banking-secure`."
     }
    },
    "required": [
     "action"
    ],
    "title": "HostActionBody",
    "type": "object",
    "description": "An action on one component instance."
   },
   "HostBulkBody": {
    "properties": {
     "action": {
      "enum": [
       "start",
       "stop",
       "restart",
       "restart_stale"
      ],
      "title": "Action",
      "type": "string",
      "description": "Action: `start`, `stop`, `restart` or `restart_stale` (only the components whose configuration changed)."
     },
     "approval_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approval Id",
      "description": "Approval granted for the service `host:<host id>` under `banking-secure`; omit it to use the approval granted to you."
     },
     "dry_run": {
      "default": false,
      "title": "Dry Run",
      "type": "boolean",
      "description": "Return the plan without creating the operation. Default false."
     }
    },
    "required": [
     "action"
    ],
    "title": "HostBulkBody",
    "type": "object",
    "description": "An action on every component of one host, in dependency order."
   },
   "HostPatch": {
    "properties": {
     "environment": {
      "anyOf": [
       {
        "maxLength": 40,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Environment",
      "description": "Platform of the host: `auto` (detected from the facts), `on_premises`, `aws`, `azure`, `gcp`, `ibm`, `ovh`, `openstack`, `oracle`..."
     },
     "labels": {
      "anyOf": [
       {
        "additionalProperties": {
         "type": "string"
        },
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Labels",
      "description": "Labels of the host as a map of strings, replacing the current ones, for example `{\"zone\": \"a\"}`."
     },
     "maintenance": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Maintenance",
      "description": "True puts the host in maintenance (no alert is raised for it), false ends it."
     },
     "rack": {
      "anyOf": [
       {
        "maxLength": 200,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Rack",
      "description": "Rack or failure domain of the host, used by the placement rules, at most 200 characters."
     }
    },
    "title": "HostPatch",
    "type": "object",
    "description": "Change of a host; a field left out or null is kept."
   },
   "HostingIn": {
    "additionalProperties": false,
    "properties": {
     "cluster_id": {
      "description": "Cluster whose `mcp-host` service hosts the server (UUID).",
      "pattern": "^[0-9a-fA-F-]{36}$",
      "title": "Cluster Id",
      "type": "string"
     },
     "limits": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/LimitsIn"
       },
       {
        "type": "null"
       }
      ],
      "description": "Limits of the hosted server; an absent value takes the default of the `mcp-host` service."
     }
    },
    "required": [
     "cluster_id"
    ],
    "title": "HostingIn",
    "type": "object",
    "description": "Hosting of a stdio MCP server."
   },
   "HubSettingsBody": {
    "additionalProperties": false,
    "properties": {
     "ca_pem": {
      "default": "",
      "maxLength": 65536,
      "title": "Ca Pem",
      "type": "string",
      "description": "Certificate authority (PEM) of the Hub when it is not publicly trusted."
     },
     "customer": {
      "default": "",
      "maxLength": 100,
      "pattern": "^[a-z0-9-]*$",
      "title": "Customer",
      "type": "string",
      "description": "Customer identifier at the Hub: lower case letters, digits and `-`."
     },
     "enforce": {
      "default": false,
      "title": "Enforce",
      "type": "boolean",
      "description": "Only install images whose digest is an approved, non revoked target. Default false."
     },
     "expected_hub": {
      "default": "",
      "maxLength": 500,
      "title": "Expected Hub",
      "type": "string"
     },
     "token": {
      "anyOf": [
       {
        "maxLength": 500,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Token",
      "description": "Access token of the Hub. Write only, sealed; null keeps the stored token."
     },
     "trusted_keys_pem": {
      "default": "",
      "maxLength": 65536,
      "title": "Trusted Keys Pem",
      "type": "string",
      "description": "Pinned Ed25519 public keys (PEM) allowed to sign the documents."
     },
     "url": {
      "default": "",
      "maxLength": 500,
      "pattern": "^(|https://[^\\s]+)$",
      "title": "Url",
      "type": "string",
      "description": "HTTPS address of the Hub, for example `https://<hub-host>`; empty for offline use."
     }
    },
    "title": "HubSettingsBody",
    "type": "object",
    "description": "Connection to the Navin Trusted Hub."
   },
   "InstallBody": {
    "additionalProperties": false,
    "properties": {
     "mirror_ca_pem": {
      "anyOf": [
       {
        "maxLength": 65536,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Mirror Ca Pem",
      "description": "Certificate authority (PEM) of the mirror."
     },
     "mirror_url": {
      "anyOf": [
       {
        "maxLength": 500,
        "pattern": "^(|https?://[^\\s]+)$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Mirror Url",
      "description": "Address of the package mirror, `http://` or `https://`; empty for the built in mirror."
     },
     "preferred_method": {
      "anyOf": [
       {
        "enum": [
         "podman",
         "binary"
        ],
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Preferred Method",
      "description": "Install method used when a service offers it and the request names none: `podman` or `binary`."
     },
     "registry": {
      "anyOf": [
       {
        "maxLength": 300,
        "pattern": "^[^\\s]*$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Registry",
      "description": "Container registry the images are pulled from, for example `<harbor-host>/navin`."
     }
    },
    "title": "InstallBody",
    "type": "object",
    "description": "Install defaults of the Manager."
   },
   "KeyIn": {
    "additionalProperties": false,
    "description": "A new virtual key for a user of the Manager or a group of the identity provider, with its models and limits.",
    "properties": {
     "assignee_kind": {
      "default": "user",
      "enum": [
       "user",
       "group"
      ],
      "title": "Assignee Kind",
      "type": "string",
      "description": "`user` (a user of the Manager, `user_id`) or `group` (a group name, `group`)."
     },
     "budget_duration": {
      "anyOf": [
       {
        "pattern": "^[1-9][0-9]{0,3}(s|m|h|d|mo)$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Budget Duration",
      "description": "Reset period of the budget: a number then `s`, `m`, `h`, `d` or `mo` (`30d`, `1mo`); null for no reset."
     },
     "group": {
      "default": "",
      "maxLength": 200,
      "title": "Group",
      "type": "string",
      "description": "Name of the group of the identity provider the key is for (`assignee_kind` group), 200 characters at most."
     },
     "max_budget": {
      "anyOf": [
       {
        "maximum": 1000000000.0,
        "minimum": 0.0,
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Budget",
      "description": "Spend budget of the key in the unit of the proxy; null for no budget."
     },
     "models": {
      "items": {
       "maxLength": 200,
       "minLength": 1,
       "type": "string"
      },
      "maxItems": 200,
      "title": "Models",
      "type": "array",
      "description": "Model ids the key may use, all among those of the profile; empty for every model of the profile."
     },
     "rpm_limit": {
      "anyOf": [
       {
        "maximum": 1000000000.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Rpm Limit",
      "description": "Requests per minute allowed; null for no limit."
     },
     "tpm_limit": {
      "anyOf": [
       {
        "maximum": 1000000000.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tpm Limit",
      "description": "Tokens per minute allowed; null for no limit."
     },
     "user_id": {
      "anyOf": [
       {
        "format": "uuid",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "User Id",
      "description": "Identifier of the enabled user of the Manager the key is for (`assignee_kind` user)."
     }
    },
    "title": "KeyIn",
    "type": "object"
   },
   "KeyLimitsIn": {
    "additionalProperties": false,
    "description": "Models and limits of a virtual key.",
    "properties": {
     "budget_duration": {
      "anyOf": [
       {
        "pattern": "^[1-9][0-9]{0,3}(s|m|h|d|mo)$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Budget Duration",
      "description": "Reset period of the budget: a number then `s`, `m`, `h`, `d` or `mo` (`30d`, `1mo`); null for no reset."
     },
     "max_budget": {
      "anyOf": [
       {
        "maximum": 1000000000.0,
        "minimum": 0.0,
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Budget",
      "description": "Spend budget of the key in the unit of the proxy; null for no budget."
     },
     "models": {
      "items": {
       "maxLength": 200,
       "minLength": 1,
       "type": "string"
      },
      "maxItems": 200,
      "title": "Models",
      "type": "array",
      "description": "Model ids the key may use, all among those of the profile; empty for every model of the profile."
     },
     "rpm_limit": {
      "anyOf": [
       {
        "maximum": 1000000000.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Rpm Limit",
      "description": "Requests per minute allowed; null for no limit."
     },
     "tpm_limit": {
      "anyOf": [
       {
        "maximum": 1000000000.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tpm Limit",
      "description": "Tokens per minute allowed; null for no limit."
     }
    },
    "title": "KeyLimitsIn",
    "type": "object"
   },
   "LdapBody": {
    "additionalProperties": false,
    "properties": {
     "bind_dn": {
      "default": "",
      "maxLength": 500,
      "title": "Bind Dn",
      "type": "string",
      "description": "Distinguished name of the service account used to search, for example `cn=navin,ou=services,dc=example,dc=internal`. Empty: anonymous bind."
     },
     "bind_password": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Bind Password",
      "description": "Password of the bind account: a string sets it, an empty string clears it, the read back object or null keeps it. Sealed at rest."
     },
     "ca_pem": {
      "default": "",
      "maxLength": 65536,
      "title": "Ca Pem",
      "type": "string",
      "description": "Certificate authority (PEM) that signed the certificate of the directory, for `ldaps://` or StartTLS."
     },
     "display_name_attribute": {
      "default": "cn",
      "maxLength": 100,
      "pattern": "^[A-Za-z0-9-]*$",
      "title": "Display Name Attribute",
      "type": "string",
      "description": "Attribute holding the display name. Default `cn`."
     },
     "email_attribute": {
      "default": "mail",
      "maxLength": 100,
      "pattern": "^[A-Za-z0-9-]*$",
      "title": "Email Attribute",
      "type": "string",
      "description": "Attribute holding the email address. Default `mail`."
     },
     "enabled": {
      "default": false,
      "title": "Enabled",
      "type": "boolean",
      "description": "Whether users may sign in through LDAP. Default false."
     },
     "group_base_dn": {
      "default": "",
      "maxLength": 500,
      "title": "Group Base Dn",
      "type": "string",
      "description": "Base DN of the group search; empty: the groups are not read."
     },
     "group_filter": {
      "default": "(objectClass=groupOfNames)",
      "maxLength": 500,
      "title": "Group Filter",
      "type": "string",
      "description": "LDAP filter selecting the groups. Default `(objectClass=groupOfNames)`."
     },
     "group_name_attribute": {
      "default": "cn",
      "maxLength": 100,
      "pattern": "^[A-Za-z0-9-]*$",
      "title": "Group Name Attribute",
      "type": "string",
      "description": "Attribute holding the group name matched by the mappings. Default `cn`."
     },
     "name": {
      "default": "LDAP",
      "maxLength": 100,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Name shown on the login page. Default `LDAP`."
     },
     "role_mappings": {
      "items": {
       "$ref": "#/components/schemas/Mapping"
      },
      "maxItems": 200,
      "title": "Role Mappings",
      "type": "array",
      "description": "Group to role mappings applied at each sign in, at most 200."
     },
     "start_tls": {
      "default": false,
      "title": "Start Tls",
      "type": "boolean",
      "description": "Upgrade `ldap://` connections with StartTLS (required for an `ldap://` URL). Default false."
     },
     "urls": {
      "items": {
       "type": "string"
      },
      "maxItems": 10,
      "title": "Urls",
      "type": "array",
      "description": "Directory servers, tried in order, for example `ldaps://<ldap-host>:636`. At most 10."
     },
     "user_base_dn": {
      "default": "",
      "maxLength": 500,
      "title": "User Base Dn",
      "type": "string",
      "description": "Base DN of the user search, for example `ou=people,dc=example,dc=internal`."
     },
     "user_filter": {
      "default": "(objectClass=person)",
      "maxLength": 500,
      "title": "User Filter",
      "type": "string",
      "description": "LDAP filter selecting the user accounts. Default `(objectClass=person)`."
     },
     "username_attribute": {
      "default": "uid",
      "maxLength": 100,
      "minLength": 1,
      "pattern": "^[A-Za-z0-9-]+$",
      "title": "Username Attribute",
      "type": "string",
      "description": "Attribute matched against the username typed at sign in. Default `uid`."
     }
    },
    "title": "LdapBody",
    "type": "object",
    "description": "Settings of the LDAP directory."
   },
   "LdapTestBody": {
    "additionalProperties": false,
    "properties": {
     "password": {
      "anyOf": [
       {
        "maxLength": 1024,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Password",
      "description": "Password of the test account. Never stored."
     },
     "username": {
      "anyOf": [
       {
        "maxLength": 200,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Username",
      "description": "Username of the test account."
     }
    },
    "title": "LdapTestBody",
    "type": "object",
    "description": "Test account of an LDAP test; without it only the bind is checked."
   },
   "LimitsIn": {
    "additionalProperties": false,
    "description": "Limits of one hosted server; an absent value takes the default of the `mcp-host` service.",
    "properties": {
     "idle_timeout_s": {
      "anyOf": [
       {
        "maximum": 86400.0,
        "minimum": 10.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Idle Timeout S",
      "description": "Idle timeout of the hosted server in seconds, 10 to 86400."
     },
     "max_concurrency": {
      "anyOf": [
       {
        "maximum": 256.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Concurrency",
      "description": "Requests served at the same time, 1 to 256."
     },
     "memory_mb": {
      "anyOf": [
       {
        "maximum": 65536.0,
        "minimum": 64.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Memory Mb",
      "description": "Memory limit of the hosted server in MB, 64 to 65536."
     },
     "request_timeout_s": {
      "anyOf": [
       {
        "maximum": 3600.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Request Timeout S",
      "description": "Longest time of one request in seconds, 1 to 3600."
     }
    },
    "title": "LimitsIn",
    "type": "object"
   },
   "LockBody": {
    "properties": {
     "reason": {
      "maxLength": 500,
      "minLength": 1,
      "title": "Reason",
      "type": "string",
      "description": "Why the cluster is locked, 1 to 500 characters; shown in the console and written to the audit trail."
     }
    },
    "required": [
     "reason"
    ],
    "title": "LockBody",
    "type": "object",
    "description": "Security lock of a cluster."
   },
   "LoginBody": {
    "additionalProperties": false,
    "properties": {
     "password": {
      "maxLength": 1024,
      "minLength": 1,
      "title": "Password",
      "type": "string",
      "description": "Password of the account (1 to 1024 characters). Never written to the logs."
     },
     "provider": {
      "default": "local",
      "enum": [
       "local",
       "ldap"
      ],
      "title": "Provider",
      "type": "string",
      "description": "Where the account lives: `local` (default) or `ldap`."
     },
     "username": {
      "maxLength": 200,
      "minLength": 1,
      "title": "Username",
      "type": "string",
      "description": "Username, case insensitive (1 to 200 characters)."
     }
    },
    "required": [
     "username",
     "password"
    ],
    "title": "LoginBody",
    "type": "object",
    "description": "Credentials of a sign in."
   },
   "LogsBody": {
    "properties": {
     "component": {
      "title": "Component",
      "type": "string",
      "description": "Name of the component."
     },
     "host_id": {
      "title": "Host Id",
      "type": "string",
      "description": "Identifier of the host running the instance."
     },
     "lines": {
      "default": 200,
      "maximum": 5000.0,
      "minimum": 1.0,
      "title": "Lines",
      "type": "integer",
      "description": "Number of last lines to read, 1 to 5000. Default 200."
     }
    },
    "required": [
     "host_id",
     "component"
    ],
    "title": "LogsBody",
    "type": "object",
    "description": "Logs to fetch."
   },
   "ManagementIn": {
    "properties": {
     "management": {
      "enum": [
       "platform",
       "client"
      ],
      "title": "Management",
      "type": "string",
      "description": "`platform` or `client`."
     }
    },
    "required": [
     "management"
    ],
    "title": "ManagementIn",
    "type": "object",
    "description": "Management mode of a host."
   },
   "Mapping": {
    "properties": {
     "cluster_id": {
      "anyOf": [
       {
        "maxLength": 64,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Cluster Id",
      "description": "Cluster the role is limited to; null for a global binding."
     },
     "group": {
      "maxLength": 500,
      "minLength": 1,
      "title": "Group",
      "type": "string",
      "description": "Group name (LDAP group name attribute, or a value of the OIDC groups claim)."
     },
     "role": {
      "maxLength": 50,
      "title": "Role",
      "type": "string",
      "description": "Role given to the members: `admin`, `security_admin`, `cluster_admin`, `operator`, `viewer` or `auditor`."
     }
    },
    "required": [
     "group",
     "role"
    ],
    "title": "Mapping",
    "type": "object",
    "description": "A group of the identity provider mapped to a role."
   },
   "MePatch": {
    "additionalProperties": false,
    "properties": {
     "display_name": {
      "anyOf": [
       {
        "maxLength": 200,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Display Name",
      "description": "Name shown in the console, at most 200 characters."
     },
     "email": {
      "anyOf": [
       {
        "maxLength": 200,
        "pattern": "^$|^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Email",
      "description": "Email address, at most 200 characters; an empty string clears it."
     },
     "language": {
      "anyOf": [
       {
        "enum": [
         "en",
         "fr"
        ],
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Language",
      "description": "Language of the console and of the messages: `en` or `fr`."
     }
    },
    "title": "MePatch",
    "type": "object",
    "description": "Change of the profile of the caller; a field left out or null is kept."
   },
   "MemberIn": {
    "properties": {
     "fault_domain": {
      "default": "",
      "title": "Fault Domain",
      "type": "string",
      "description": "Fault domain of the member (rack, zone). Default empty."
     },
     "host_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Host Id",
      "description": "Host of the member in the cluster; null for a member outside the hosts (Kubernetes, external)."
     },
     "name": {
      "maxLength": 120,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Name of the member, 1 to 120 characters."
     },
     "role": {
      "default": "any",
      "enum": [
       "primary",
       "replica",
       "witness",
       "any"
      ],
      "title": "Role",
      "type": "string",
      "description": "Role: `primary`, `replica`, `witness` or `any` (default)."
     }
    },
    "required": [
     "name"
    ],
    "title": "MemberIn",
    "type": "object",
    "description": "A member of a high availability group."
   },
   "MfaConfirmBody": {
    "additionalProperties": false,
    "properties": {
     "code": {
      "maxLength": 20,
      "minLength": 1,
      "title": "Code",
      "type": "string",
      "description": "Current code (6 digits) of the pending secret."
     }
    },
    "required": [
     "code"
    ],
    "title": "MfaConfirmBody",
    "type": "object",
    "description": "Confirmation of a self service enrollment."
   },
   "MfaDisableBody": {
    "additionalProperties": false,
    "properties": {
     "code": {
      "anyOf": [
       {
        "maxLength": 20,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Code",
      "description": "Current TOTP code, required for an LDAP or OIDC account."
     },
     "password": {
      "anyOf": [
       {
        "maxLength": 1024,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Password",
      "description": "Password of the account, required for a local account."
     }
    },
    "title": "MfaDisableBody",
    "type": "object",
    "description": "Proof of identity to turn the second factor off."
   },
   "MfaVerifyBody": {
    "additionalProperties": false,
    "properties": {
     "code": {
      "anyOf": [
       {
        "maxLength": 20,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Code",
      "description": "Current TOTP code (6 digits). Takes precedence over `recovery_code`."
     },
     "mfa_token": {
      "maxLength": 200,
      "minLength": 1,
      "title": "Mfa Token",
      "type": "string",
      "description": "Challenge token returned by the login (`mfa_token`), valid 5 minutes and 5 attempts."
     },
     "recovery_code": {
      "anyOf": [
       {
        "maxLength": 64,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Recovery Code",
      "description": "One of the recovery codes given at enrollment; each works once."
     }
    },
    "required": [
     "mfa_token"
    ],
    "title": "MfaVerifyBody",
    "type": "object",
    "description": "Second factor of a sign in: a TOTP code or a recovery code."
   },
   "ModeBody": {
    "properties": {
     "approval_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approval Id",
      "description": "Approval granted for a stopping mode under `banking-secure`."
     },
     "drain_timeout_s": {
      "anyOf": [
       {
        "maximum": 3600.0,
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Drain Timeout S",
      "description": "For `drain`: seconds given to the transactions in flight before the processes are killed, 0 to 3600. Default 300."
     },
     "mode": {
      "enum": [
       "drain",
       "scale_to_zero",
       "security_suspend",
       "emergency_stop",
       "disable",
       "quarantine",
       "maintenance",
       "enable"
      ],
      "title": "Mode",
      "type": "string",
      "description": "Mode: `drain`, `scale_to_zero`, `security_suspend`, `emergency_stop`, `disable`, `quarantine`, `maintenance` or `enable`."
     },
     "reason": {
      "anyOf": [
       {
        "maxLength": 500,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Reason",
      "description": "Why the mode is applied, at most 500 characters; required to lift a security suspension."
     }
    },
    "required": [
     "mode"
    ],
    "title": "ModeBody",
    "type": "object",
    "description": "An operating mode to apply."
   },
   "ModelIn": {
    "additionalProperties": false,
    "description": "One model of the gateway: its LiteLLM model_name, a label and the optional limits.",
    "properties": {
     "context_window": {
      "anyOf": [
       {
        "maximum": 100000000.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Context Window",
      "description": "Context window in tokens, positive."
     },
     "id": {
      "maxLength": 200,
      "minLength": 1,
      "title": "Id",
      "type": "string",
      "description": "LiteLLM `model_name`, unique in the profile."
     },
     "label": {
      "default": "",
      "maxLength": 120,
      "title": "Label",
      "type": "string",
      "description": "Name shown in Navin; the id when empty."
     },
     "max_output_tokens": {
      "anyOf": [
       {
        "maximum": 100000000.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Output Tokens",
      "description": "Maximum output tokens, positive."
     },
     "reasoning_effort": {
      "anyOf": [
       {
        "enum": [
         "none",
         "minimal",
         "low",
         "medium",
         "high"
        ],
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Reasoning Effort",
      "description": "`none`, `minimal`, `low`, `medium` or `high`."
     },
     "vision": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Vision",
      "description": "The model accepts images."
     }
    },
    "required": [
     "id"
    ],
    "title": "ModelIn",
    "type": "object"
   },
   "OidcBody": {
    "additionalProperties": false,
    "properties": {
     "client_id": {
      "maxLength": 300,
      "minLength": 1,
      "title": "Client Id",
      "type": "string",
      "description": "Client identifier registered at the provider."
     },
     "client_secret": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Client Secret",
      "description": "Client secret: a string sets it, an empty string clears it, the read back object or null keeps it. Sealed at rest."
     },
     "enabled": {
      "default": true,
      "title": "Enabled",
      "type": "boolean",
      "description": "Whether the provider is offered on the login page. Default true."
     },
     "groups_claim": {
      "default": "groups",
      "maxLength": 100,
      "minLength": 1,
      "title": "Groups Claim",
      "type": "string",
      "description": "Claim of the ID token holding the groups. Default `groups`."
     },
     "issuer": {
      "maxLength": 500,
      "minLength": 9,
      "pattern": "^https://[^\\s]+$",
      "title": "Issuer",
      "type": "string",
      "description": "HTTPS issuer URL, for example `https://<sso-host>/realms/navin`."
     },
     "name": {
      "maxLength": 100,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Unique name shown on the login page, 1 to 100 characters."
     },
     "role_mappings": {
      "items": {
       "$ref": "#/components/schemas/Mapping"
      },
      "maxItems": 200,
      "title": "Role Mappings",
      "type": "array",
      "description": "Group to role mappings applied at each sign in, at most 200."
     },
     "scopes": {
      "items": {
       "type": "string"
      },
      "maxItems": 20,
      "title": "Scopes",
      "type": "array",
      "description": "Scopes requested; must include `openid`. Default `openid`, `profile`, `email`."
     },
     "username_claim": {
      "default": "preferred_username",
      "maxLength": 100,
      "minLength": 1,
      "title": "Username Claim",
      "type": "string",
      "description": "Claim used as the username. Default `preferred_username`."
     }
    },
    "required": [
     "name",
     "issuer",
     "client_id"
    ],
    "title": "OidcBody",
    "type": "object",
    "description": "Settings of an OIDC provider."
   },
   "ParametersIn": {
    "properties": {
     "limits": {
      "additionalProperties": {
       "anyOf": [
        {
         "type": "integer"
        },
        {
         "type": "string"
        }
       ]
      },
      "title": "Limits",
      "type": "object",
      "description": "Resource limits for every user: keys `nofile`, `nproc`, `memlock`; values a number or a string such as `unlimited`."
     },
     "sysctl": {
      "additionalProperties": {
       "anyOf": [
        {
         "type": "integer"
        },
        {
         "type": "string"
        }
       ]
      },
      "title": "Sysctl",
      "type": "object",
      "description": "Sysctl settings, for example `{\"vm.max_map_count\": 262144}`. Keys: lower case letters, digits, `_`, `.` and `-`."
     }
    },
    "title": "ParametersIn",
    "type": "object",
    "description": "Kernel parameters of a host."
   },
   "PasswordChangeBody": {
    "additionalProperties": false,
    "properties": {
     "current_password": {
      "anyOf": [
       {
        "maxLength": 1024,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Current Password",
      "description": "Current password, required when signed in."
     },
     "new_password": {
      "maxLength": 1024,
      "minLength": 1,
      "title": "New Password",
      "type": "string",
      "description": "New password; must follow the password policy."
     },
     "password_change_token": {
      "anyOf": [
       {
        "maxLength": 200,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Password Change Token",
      "description": "Token from `details.password_change_token` of a `403 password_expired` login error, valid 5 minutes."
     }
    },
    "required": [
     "new_password"
    ],
    "title": "PasswordChangeBody",
    "type": "object",
    "description": "Change of a password, signed in or with a password change token."
   },
   "PasswordReset": {
    "additionalProperties": false,
    "properties": {
     "must_change_password": {
      "default": true,
      "title": "Must Change Password",
      "type": "boolean",
      "description": "When true (default), the user must choose a new password at the next sign in."
     },
     "new_password": {
      "maxLength": 1024,
      "minLength": 1,
      "title": "New Password",
      "type": "string",
      "description": "New password; must follow the password policy. Write only."
     }
    },
    "required": [
     "new_password"
    ],
    "title": "PasswordReset",
    "type": "object",
    "description": "Password set by an administrator."
   },
   "PdbIn": {
    "additionalProperties": false,
    "properties": {
     "max_unavailable": {
      "anyOf": [
       {
        "maximum": 1000.0,
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "pattern": "^(100|[1-9]?[0-9])%$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Unavailable",
      "description": "Pods that may be down at the same time: a number (0 to 1000) or a percentage such as `25%`."
     },
     "min_available": {
      "anyOf": [
       {
        "maximum": 1000.0,
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "pattern": "^(100|[1-9]?[0-9])%$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Min Available",
      "description": "Pods that must stay up: a number (0 to 1000) or a percentage such as `50%`."
     }
    },
    "title": "PdbIn",
    "type": "object",
    "description": "Pod disruption budget: exactly one of `min_available` and `max_unavailable`."
   },
   "PlanIn": {
    "properties": {
     "encryption_key_ref": {
      "minLength": 1,
      "title": "Encryption Key Ref",
      "type": "string",
      "description": "Reference of the key that encrypts the backups."
     },
     "immutability_required": {
      "default": false,
      "title": "Immutability Required",
      "type": "boolean",
      "description": "Require an immutable (WORM) target with object lock and retention. Default false."
     },
     "interval_seconds": {
      "minimum": 60.0,
      "title": "Interval Seconds",
      "type": "integer",
      "description": "Time between two backups in seconds, 60 or more."
     },
     "name": {
      "maxLength": 100,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Name of the plan, 1 to 100 characters."
     },
     "retention_days": {
      "minimum": 1.0,
      "title": "Retention Days",
      "type": "integer",
      "description": "Days a backup is kept before it can be deleted, 1 or more."
     },
     "scope": {
      "additionalProperties": true,
      "title": "Scope",
      "type": "object",
      "description": "What is backed up (clusters, services, data sets), as an object."
     },
     "target_id": {
      "title": "Target Id",
      "type": "string",
      "description": "Identifier of the backup target."
     },
     "window_seconds": {
      "default": 3600,
      "minimum": 0.0,
      "title": "Window Seconds",
      "type": "integer",
      "description": "Tolerance after the interval before a backup is reported late, in seconds. Default 3600."
     }
    },
    "required": [
     "name",
     "target_id",
     "scope",
     "interval_seconds",
     "encryption_key_ref",
     "retention_days"
    ],
    "title": "PlanIn",
    "type": "object",
    "description": "A new backup plan."
   },
   "PolicyBody": {
    "additionalProperties": false,
    "properties": {
     "lockout_minutes": {
      "maximum": 1440.0,
      "minimum": 1.0,
      "title": "Lockout Minutes",
      "type": "integer",
      "description": "Duration of a lockout in minutes, 1 to 1440."
     },
     "lockout_threshold": {
      "maximum": 20.0,
      "minimum": 3.0,
      "title": "Lockout Threshold",
      "type": "integer",
      "description": "Failed sign ins that lock the account, 3 to 20."
     },
     "mfa_required_roles": {
      "items": {
       "type": "string"
      },
      "maxItems": 6,
      "title": "Mfa Required Roles",
      "type": "array",
      "description": "Roles whose holders must use MFA (enrollment forced at sign in when MFA is turned on)."
     },
     "password_history": {
      "maximum": 24.0,
      "minimum": 0.0,
      "title": "Password History",
      "type": "integer",
      "description": "Number of previous passwords that cannot be reused, 0 to 24."
     },
     "password_max_age_days": {
      "maximum": 3650.0,
      "minimum": 0.0,
      "title": "Password Max Age Days",
      "type": "integer",
      "description": "Days after which a local password must be changed, 0 to 3650; 0: never."
     },
     "password_min_length": {
      "maximum": 128.0,
      "minimum": 8.0,
      "title": "Password Min Length",
      "type": "integer",
      "description": "Minimum length of a password, 8 to 128 characters."
     },
     "session_absolute_hours": {
      "maximum": 72.0,
      "minimum": 1.0,
      "title": "Session Absolute Hours",
      "type": "integer",
      "description": "Longest life of a session in hours, 1 to 72."
     },
     "session_idle_minutes": {
      "maximum": 480.0,
      "minimum": 5.0,
      "title": "Session Idle Minutes",
      "type": "integer",
      "description": "Idle time after which a session ends, 5 to 480 minutes."
     }
    },
    "required": [
     "password_min_length",
     "password_history",
     "password_max_age_days",
     "lockout_threshold",
     "lockout_minutes",
     "session_idle_minutes",
     "session_absolute_hours",
     "mfa_required_roles"
    ],
    "title": "PolicyBody",
    "type": "object",
    "description": "Security policy of the console."
   },
   "PolicyIn": {
    "properties": {
     "automatic": {
      "default": false,
      "title": "Automatic",
      "type": "boolean",
      "description": "Fail over automatically when the primary is lost. Default false (operator decision)."
     },
     "fencing": {
      "default": "lease",
      "enum": [
       "none",
       "lease",
       "stonith",
       "promote_demote"
      ],
      "title": "Fencing",
      "type": "string",
      "description": "How the old primary is isolated: `none`, `lease` (default), `stonith` or `promote_demote`."
     },
     "max_lag_seconds": {
      "anyOf": [
       {
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Lag Seconds",
      "description": "Largest replication lag accepted for a replica to be promoted, in seconds."
     }
    },
    "title": "PolicyIn",
    "type": "object",
    "description": "Failover policy of a group."
   },
   "PreflightBody": {
    "properties": {
     "hosts": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "maxItems": 1000,
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Hosts",
      "description": "Host identifiers to check, at most 1000; null: every host."
     },
     "services": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "maxItems": 200,
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Services",
      "description": "Services to check, at most 200; null: every service."
     }
    },
    "title": "PreflightBody",
    "type": "object",
    "description": "Scope of an installation preflight."
   },
   "PreflightIn": {
    "additionalProperties": false,
    "properties": {
     "certificate": {
      "anyOf": [
       {
        "maxLength": 20000,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Certificate",
      "description": "OpenSSH user certificate of the key, signed by an approved CA."
     },
     "cluster_id": {
      "title": "Cluster Id",
      "type": "string",
      "description": "Cluster the host would join."
     },
     "disk_paths": {
      "items": {
       "type": "string"
      },
      "maxItems": 10,
      "title": "Disk Paths",
      "type": "array",
      "description": "Paths whose free space is checked, at most 10. Default `/`."
     },
     "expected_ip": {
      "maxLength": 64,
      "minLength": 1,
      "title": "Expected Ip",
      "type": "string",
      "description": "IP address the FQDN must resolve to."
     },
     "fqdn": {
      "maxLength": 253,
      "minLength": 1,
      "title": "Fqdn",
      "type": "string",
      "description": "FQDN of the host, checked forward and reverse in DNS."
     },
     "jumps": {
      "items": {
       "$ref": "#/components/schemas/EndpointIn"
      },
      "maxItems": 4,
      "title": "Jumps",
      "type": "array",
      "description": "Jump hosts to go through, at most 4."
     },
     "private_key": {
      "maxLength": 20000,
      "minLength": 20,
      "title": "Private Key",
      "type": "string",
      "description": "Private SSH key of the operator. Kept in memory for the run only."
     },
     "required_ports": {
      "items": {
       "type": "integer"
      },
      "maxItems": 50,
      "title": "Required Ports",
      "type": "array",
      "description": "TCP ports that must be free on the host (a port already listening is reported), at most 50. Default `[8461]`."
     },
     "ssh_user": {
      "anyOf": [
       {
        "maxLength": 32,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Ssh User",
      "description": "SSH account; default: the bootstrap user of the SSH policy."
     },
     "target": {
      "$ref": "#/components/schemas/EndpointIn",
      "description": "The host to check."
     }
    },
    "required": [
     "cluster_id",
     "target",
     "private_key",
     "fqdn",
     "expected_ip"
    ],
    "title": "PreflightIn",
    "type": "object",
    "description": "SSH access and expectations of a host preflight. A password field is refused."
   },
   "ProfileBody": {
    "properties": {
     "profile": {
      "enum": [
       "development",
       "standard",
       "banking-secure",
       "air-gapped",
       "hybrid"
      ],
      "title": "Profile",
      "type": "string",
      "description": "`development`, `standard`, `banking-secure`, `air-gapped` or `hybrid`."
     }
    },
    "required": [
     "profile"
    ],
    "title": "ProfileBody",
    "type": "object",
    "description": "Installation profile of a cluster."
   },
   "ProfileIn": {
    "additionalProperties": false,
    "description": "A Navin SM profile.",
    "properties": {
     "auth_mode": {
      "default": "user_key",
      "enum": [
       "user_key",
       "shared_key",
       "none"
      ],
      "title": "Auth Mode",
      "type": "string",
      "description": "`user_key`, `shared_key` or `none`."
     },
     "base_url": {
      "maxLength": 2048,
      "minLength": 1,
      "title": "Base Url",
      "type": "string",
      "description": "`http` or `https` address of the proxy, without `/chat/completions`."
     },
     "ca_bundle": {
      "default": "",
      "maxLength": 1024,
      "title": "Ca Bundle",
      "type": "string",
      "description": "Path of a PEM file on the workstations, trusted on top of the public roots; refused with `use_manager_ca`."
     },
     "default_model": {
      "maxLength": 200,
      "minLength": 1,
      "title": "Default Model",
      "type": "string",
      "description": "One of the model ids."
     },
     "exclusive": {
      "default": true,
      "title": "Exclusive",
      "type": "boolean",
      "description": "Only this gateway can be used (default true)."
     },
     "headers": {
      "additionalProperties": {
       "maxLength": 4096,
       "type": "string"
      },
      "maxProperties": 50,
      "title": "Headers",
      "type": "object",
      "description": "Extra HTTP headers; credential headers are refused."
     },
     "litellm_cluster_id": {
      "anyOf": [
       {
        "format": "uuid",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Litellm Cluster Id",
      "description": "Cluster of the LiteLLM service installed by the Manager the profile is linked to; with `litellm_service`, or neither. The link gives the discovery its master key and lets the Manager issue the virtual keys."
     },
     "litellm_service": {
      "default": "",
      "maxLength": 100,
      "title": "Litellm Service",
      "type": "string",
      "description": "Name of the installed LiteLLM service in that cluster (100 characters at most)."
     },
     "models": {
      "items": {
       "$ref": "#/components/schemas/ModelIn"
      },
      "maxItems": 500,
      "title": "Models",
      "type": "array",
      "description": "1 to 200 models."
     },
     "org_id": {
      "maxLength": 200,
      "minLength": 1,
      "title": "Org Id",
      "type": "string",
      "description": "Organization identifier: 1 to 64 lowercase letters, digits and hyphens, unique."
     },
     "org_name": {
      "maxLength": 120,
      "minLength": 1,
      "title": "Org Name",
      "type": "string",
      "description": "Organization name shown in Navin, 120 characters at most (the limit of Navin)."
     },
     "policy": {
      "$ref": "#/components/schemas/SmPolicyIn",
      "description": "Managed policy."
     },
     "routes": {
      "additionalProperties": {
       "maxLength": 200,
       "type": "string"
      },
      "maxProperties": 50,
      "title": "Routes",
      "type": "object",
      "description": "Navin task roles to model ids."
     },
     "shared_key_ref": {
      "anyOf": [
       {
        "format": "uuid",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Shared Key Ref",
      "description": "Vault entry holding the shared key; required with `shared_key`, refused otherwise."
     },
     "support_contact": {
      "default": "",
      "maxLength": 200,
      "title": "Support Contact",
      "type": "string",
      "description": "Contact shown to users when the gateway fails, 200 characters at most."
     },
     "use_manager_ca": {
      "default": false,
      "title": "Use Manager Ca",
      "type": "boolean",
      "description": "Ship the CA of the Manager in the deployment bundle and point `gateway.caBundle` at its path on the system (`/etc/navin/navin-sm-ca.pem`, `/Library/Application Support/Navin/navin-sm-ca.pem`, `C:\\ProgramData\\Navin\\navin-sm-ca.pem`); the export and the preview then need `os`."
     }
    },
    "required": [
     "org_id",
     "org_name",
     "base_url",
     "default_model"
    ],
    "title": "ProfileIn",
    "type": "object"
   },
   "ProxyBody": {
    "additionalProperties": false,
    "description": "Corporate proxy of the managed hosts: http(s) URLs without credentials, empty string to clear.",
    "properties": {
     "http_proxy": {
      "anyOf": [
       {
        "maxLength": 500,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Http Proxy",
      "description": "Proxy for HTTP traffic, for example `http://<proxy-host>:3128`."
     },
     "https_proxy": {
      "anyOf": [
       {
        "maxLength": 500,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Https Proxy",
      "description": "Proxy for HTTPS traffic."
     },
     "no_proxy": {
      "anyOf": [
       {
        "maxLength": 2000,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "No Proxy",
      "description": "Comma separated hosts, domains and networks reached without the proxy, for example `<internal-domain>,10.0.0.0/8`."
     }
    },
    "title": "ProxyBody",
    "type": "object"
   },
   "ReconcileBody": {
    "properties": {
     "approval_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approval Id",
      "description": "Identifier of the approved request (four-eyes approval) that authorizes this action."
     },
     "restart": {
      "default": false,
      "title": "Restart",
      "type": "boolean",
      "description": "Restart the instance after rewriting its files. Default false."
     }
    },
    "title": "ReconcileBody",
    "type": "object",
    "description": "Options of a drift reconcile."
   },
   "RegisterIn": {
    "properties": {
     "agent_version": {
      "default": "",
      "maxLength": 40,
      "title": "Agent Version",
      "type": "string",
      "description": "Version of the agent, at most 40 characters."
     },
     "bootstrap_token": {
      "maxLength": 200,
      "minLength": 20,
      "title": "Bootstrap Token",
      "type": "string",
      "description": "Bootstrap token created for the cluster (20 to 200 characters). Write only, stored as a hash."
     },
     "csr_pem": {
      "maxLength": 20000,
      "minLength": 100,
      "title": "Csr Pem",
      "type": "string",
      "description": "Certificate signing request of the agent key, PEM encoded. Only its public key is used."
     },
     "facts": {
      "additionalProperties": true,
      "title": "Facts",
      "type": "object",
      "description": "Facts collected on the host: operating system, architecture, CPU, memory, disks, network..."
     },
     "fqdn": {
      "maxLength": 253,
      "minLength": 1,
      "title": "Fqdn",
      "type": "string",
      "description": "Fully qualified domain name of the host, for example `<db1-host>`. Identifies the host in its cluster."
     },
     "hostname": {
      "maxLength": 253,
      "minLength": 1,
      "title": "Hostname",
      "type": "string",
      "description": "Short host name, 1 to 253 characters."
     },
     "ip": {
      "default": "",
      "maxLength": 64,
      "title": "Ip",
      "type": "string",
      "description": "IP address of the host. Empty: the source address of the request is used."
     },
     "service_driver": {
      "default": "systemd",
      "pattern": "^(systemd|process)$",
      "title": "Service Driver",
      "type": "string",
      "description": "How the agent runs the services: `systemd` (default) or `process` (plain processes, for containers without systemd)."
     }
    },
    "required": [
     "bootstrap_token",
     "hostname",
     "fqdn",
     "csr_pem"
    ],
    "title": "RegisterIn",
    "type": "object",
    "description": "Registration request of an agent."
   },
   "RestorePlanIn": {
    "properties": {
     "artifact_id": {
      "title": "Artifact Id",
      "type": "string",
      "description": "Identifier of the backup artefact to restore."
     },
     "config_snapshot": {
      "additionalProperties": true,
      "default": {},
      "title": "Config Snapshot",
      "type": "object",
      "description": "Configuration recorded with the plan for the operator; it is never applied automatically."
     },
     "environment": {
      "pattern": "^(isolated|staging|production)$",
      "title": "Environment",
      "type": "string",
      "description": "Where to restore: `isolated`, `staging` or `production`; must be the environment declared for `target_name`."
     },
     "target_name": {
      "default": "",
      "maxLength": 100,
      "title": "Target Name",
      "type": "string",
      "description": "Name of a destination of `GET /restore-targets`. Without it the plan supports the dry run only and its execution is refused (`501 restore_executor_unavailable`)."
     },
     "target_versions": {
      "additionalProperties": {
       "type": "string"
      },
      "default": {},
      "title": "Target Versions",
      "type": "object",
      "description": "Versions of the target components, compared with the backed up ones (same major version required)."
     }
    },
    "required": [
     "artifact_id",
     "environment"
    ],
    "title": "RestorePlanIn",
    "type": "object",
    "description": "A restore to plan."
   },
   "RestoreTestIn": {
    "properties": {
     "inject_corruption": {
      "default": false,
      "title": "Inject Corruption",
      "type": "boolean",
      "description": "Corrupt the copy on purpose to prove the test detects it. Default false."
     }
    },
    "title": "RestoreTestIn",
    "type": "object",
    "description": "Options of a restore test."
   },
   "RetentionBody": {
    "additionalProperties": false,
    "properties": {
     "metrics_days": {
      "anyOf": [
       {
        "maximum": 3650.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Metrics Days",
      "description": "Days of host metrics kept, 1 to 3650."
     },
     "operations_days": {
      "anyOf": [
       {
        "maximum": 3650.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Operations Days",
      "description": "Days of finished operations kept, 1 to 3650."
     },
     "task_logs_days": {
      "anyOf": [
       {
        "maximum": 3650.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Task Logs Days",
      "description": "Days of task logs kept, 1 to 3650."
     }
    },
    "title": "RetentionBody",
    "type": "object",
    "description": "How long the Manager keeps its data."
   },
   "RoleItem": {
    "properties": {
     "cluster_id": {
      "anyOf": [
       {
        "maxLength": 64,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Cluster Id",
      "description": "Cluster the role is limited to; null or absent for a global binding. Not allowed for the global only roles."
     },
     "role": {
      "maxLength": 50,
      "title": "Role",
      "type": "string",
      "description": "Role name: `admin`, `security_admin`, `cluster_admin`, `operator`, `viewer` or `auditor`."
     }
    },
    "required": [
     "role"
    ],
    "title": "RoleItem",
    "type": "object",
    "description": "A role binding: a role, globally or on one cluster."
   },
   "RolesBody": {
    "additionalProperties": false,
    "properties": {
     "roles": {
      "items": {
       "$ref": "#/components/schemas/RoleItem"
      },
      "maxItems": 50,
      "title": "Roles",
      "type": "array",
      "description": "Every manual binding of the user, at most 50; an empty list removes them all."
     }
    },
    "required": [
     "roles"
    ],
    "title": "RolesBody",
    "type": "object",
    "description": "Manual role bindings of a user."
   },
   "RotateBody": {
    "description": "New password of the console account (generated when omitted) and how the service restarts to use it.",
    "properties": {
     "approval_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approval Id",
      "description": "Approval granted for the apply under `banking-secure`."
     },
     "batch_size": {
      "default": 1,
      "maximum": 100.0,
      "minimum": 1.0,
      "title": "Batch Size",
      "type": "integer",
      "description": "Hosts restarted at the same time by a rolling restart, 1 to 100. Default 1."
     },
     "password": {
      "anyOf": [
       {
        "maxLength": 256,
        "minLength": 16,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Password",
      "description": "New password, 16 to 256 characters; generated when omitted. Write only."
     },
     "restart": {
      "default": "rolling",
      "enum": [
       "rolling",
       "all"
      ],
      "title": "Restart",
      "type": "string",
      "description": "Restart policy: `rolling` (default) or `all`."
     }
    },
    "title": "RotateBody",
    "type": "object"
   },
   "RotateIn": {
    "properties": {
     "service": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Service",
      "description": "Only rotate the certificates of this service; null: every service of the cluster."
     }
    },
    "title": "RotateIn",
    "type": "object",
    "description": "Scope of a certificate rotation."
   },
   "ScanBody": {
    "properties": {
     "hosts": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "maxItems": 1000,
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Hosts",
      "description": "Host identifiers to scan, at most 1000; null: every host."
     }
    },
    "title": "ScanBody",
    "type": "object",
    "description": "Scope of a drift scan."
   },
   "SecretRefIn": {
    "additionalProperties": false,
    "properties": {
     "key": {
      "anyOf": [
       {
        "maxLength": 253,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Key",
      "description": "Key in the Secret; optional, passed to the operator when set."
     },
     "name": {
      "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
      "title": "Name",
      "type": "string",
      "description": "Name of the reference (DNS label)."
     },
     "secret_name": {
      "maxLength": 253,
      "pattern": "^[a-z0-9]([-a-z0-9.]*[a-z0-9])?$",
      "title": "Secret Name",
      "type": "string",
      "description": "Name of the Secret in the managed namespace."
     },
     "value_path": {
      "maxLength": 253,
      "pattern": "^[A-Za-z0-9_-]+(\\.[A-Za-z0-9_-]+)*$",
      "title": "Value Path",
      "type": "string",
      "description": "Dotted path of the chart value to fill, for example `auth.password`."
     }
    },
    "required": [
     "name",
     "secret_name",
     "value_path"
    ],
    "title": "SecretRefIn",
    "type": "object",
    "description": "A chart value taken from a Kubernetes Secret."
   },
   "ServerIn": {
    "additionalProperties": false,
    "description": "An MCP server of a tenant project: from a preset (`preset` and `values`, `url` for the internal address when the preset URL is not internal) or custom (`url` or `command`).",
    "properties": {
     "allowed_tools": {
      "items": {
       "type": "string"
      },
      "maxItems": 500,
      "minItems": 1,
      "title": "Allowed Tools",
      "type": "array",
      "description": "Tools the server may expose, 1 to 500 names. Default `[\"*\"]` (every tool)."
     },
     "args": {
      "items": {
       "type": "string"
      },
      "maxItems": 64,
      "title": "Args",
      "type": "array",
      "description": "Arguments of the stdio command, at most 64."
     },
     "command": {
      "anyOf": [
       {
        "maxLength": 512,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Command",
      "description": "Command of a custom stdio server, for example `mcp-server-git`. No shell is used."
     },
     "env": {
      "additionalProperties": {
       "type": "string"
      },
      "maxProperties": 64,
      "title": "Env",
      "type": "object",
      "description": "Environment of a custom stdio server, at most 64 variables; sealed."
     },
     "headers": {
      "additionalProperties": {
       "type": "string"
      },
      "maxProperties": 32,
      "title": "Headers",
      "type": "object",
      "description": "HTTP headers of a custom HTTP server, at most 32; sealed."
     },
     "name": {
      "anyOf": [
       {
        "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name",
      "description": "Unique name of the server in the project (slug); default: the name of the preset; required for a custom server."
     },
     "preset": {
      "anyOf": [
       {
        "maxLength": 120,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Preset",
      "description": "Name of the preset of the Navin library."
     },
     "project": {
      "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
      "title": "Project",
      "type": "string",
      "description": "Project slug."
     },
     "status": {
      "default": "active",
      "pattern": "^(active|disabled)$",
      "title": "Status",
      "type": "string",
      "description": "`active` (default) or `disabled`."
     },
     "tenant": {
      "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
      "title": "Tenant",
      "type": "string",
      "description": "Tenant slug."
     },
     "transport": {
      "anyOf": [
       {
        "pattern": "^(stdio|streamable_http|sse)$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Transport",
      "description": "`stdio`, `streamable_http` or `sse`; default: `stdio` with a command, else `streamable_http`."
     },
     "url": {
      "anyOf": [
       {
        "maxLength": 2048,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Url",
      "description": "Internal URL of the server, for example `https://<mcp-host>/mcp`; must be a private address or an allowed internal host."
     },
     "values": {
      "additionalProperties": {
       "type": "string"
      },
      "maxProperties": 64,
      "title": "Values",
      "type": "object",
      "description": "Values of the fields of the preset, at most 64; secret fields are sealed."
     }
    },
    "required": [
     "tenant",
     "project"
    ],
    "title": "ServerIn",
    "type": "object"
   },
   "ServerPatch": {
    "additionalProperties": false,
    "description": "Fields to change. `values` is merged with the stored values (an empty string forgets a value); `headers` and `env` replace the stored ones (custom servers only).",
    "properties": {
     "allowed_tools": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "maxItems": 500,
        "minItems": 1,
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Allowed Tools",
      "description": "New list of allowed tools, 1 to 500 names."
     },
     "args": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "maxItems": 64,
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Args",
      "description": "New arguments of the command (custom servers only)."
     },
     "command": {
      "anyOf": [
       {
        "maxLength": 512,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Command",
      "description": "New command (custom servers only)."
     },
     "env": {
      "anyOf": [
       {
        "additionalProperties": {
         "type": "string"
        },
        "maxProperties": 64,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Env",
      "description": "New environment, replacing the stored one (custom servers only)."
     },
     "headers": {
      "anyOf": [
       {
        "additionalProperties": {
         "type": "string"
        },
        "maxProperties": 32,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Headers",
      "description": "New HTTP headers, replacing the stored ones (custom servers only)."
     },
     "status": {
      "anyOf": [
       {
        "pattern": "^(active|disabled)$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Status",
      "description": "`active` or `disabled`; disabling a hosted server withdraws it."
     },
     "url": {
      "anyOf": [
       {
        "maxLength": 2048,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Url",
      "description": "New internal URL (custom servers only)."
     },
     "values": {
      "anyOf": [
       {
        "additionalProperties": {
         "type": "string"
        },
        "maxProperties": 64,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Values",
      "description": "Values of preset fields to merge; an empty string forgets a value."
     }
    },
    "title": "ServerPatch",
    "type": "object"
   },
   "ServicesBody": {
    "properties": {
     "auto_dependencies": {
      "default": true,
      "title": "Auto Dependencies",
      "type": "boolean",
      "description": "Add the missing dependencies to the install. Default true."
     },
     "ha_acknowledged": {
      "default": false,
      "title": "Ha Acknowledged",
      "type": "boolean",
      "description": "Accept a topology below the high availability requirements. Default false."
     },
     "service_check": {
      "default": true,
      "title": "Service Check",
      "type": "boolean",
      "description": "Run the service check of each service at the end. Default true."
     },
     "services": {
      "items": {
       "additionalProperties": true,
       "type": "object"
      },
      "maxItems": 100,
      "minItems": 1,
      "title": "Services",
      "type": "array",
      "description": "Services to install, 1 to 100. Each item: `name` (required), `version`, `mode`, `method`, `managed`, `placements` (`{component: [host ids]}`), `config` and `bindings` (to other services)."
     },
     "start": {
      "default": true,
      "title": "Start",
      "type": "boolean",
      "description": "Start the services once installed. Default true."
     }
    },
    "required": [
     "services"
    ],
    "title": "ServicesBody",
    "type": "object",
    "description": "An install request."
   },
   "SettingsBody": {
    "additionalProperties": false,
    "properties": {
     "default_language": {
      "anyOf": [
       {
        "enum": [
         "en",
         "fr"
        ],
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Default Language",
      "description": "Language of the console for users who did not choose one: `en` or `fr`."
     },
     "install": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/InstallBody"
       },
       {
        "type": "null"
       }
      ],
      "description": "Install defaults."
     },
     "proxy": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/ProxyBody"
       },
       {
        "type": "null"
       }
      ],
      "description": "Corporate proxy of the managed hosts."
     },
     "retention": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/RetentionBody"
       },
       {
        "type": "null"
       }
      ],
      "description": "Data retention."
     },
     "site_name": {
      "anyOf": [
       {
        "maxLength": 100,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Site Name",
      "description": "Name of the site shown in the console, 1 to 100 characters."
     },
     "smtp": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/SmtpBody"
       },
       {
        "type": "null"
       }
      ],
      "description": "Outgoing mail server."
     },
     "syslog": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/SyslogBody"
       },
       {
        "type": "null"
       }
      ],
      "description": "Remote syslog server."
     }
    },
    "title": "SettingsBody",
    "type": "object",
    "description": "Change of the settings; a section left out or null is kept."
   },
   "SetupBody": {
    "additionalProperties": false,
    "properties": {
     "display_name": {
      "anyOf": [
       {
        "maxLength": 200,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Display Name",
      "description": "Name shown in the console; the username when empty."
     },
     "password": {
      "maxLength": 1024,
      "minLength": 1,
      "title": "Password",
      "type": "string",
      "description": "Password; must follow the password policy. Write only."
     },
     "username": {
      "maxLength": 100,
      "minLength": 1,
      "pattern": "^[A-Za-z0-9._@-]+$",
      "title": "Username",
      "type": "string",
      "description": "Username: letters, digits, `.`, `_`, `@` and `-`, at most 100 characters."
     }
    },
    "required": [
     "username",
     "password"
    ],
    "title": "SetupBody",
    "type": "object",
    "description": "First administrator of a new Manager."
   },
   "SmPolicyIn": {
    "additionalProperties": false,
    "description": "Managed policy of the file.",
    "properties": {
     "allow": {
      "items": {
       "maxLength": 200,
       "minLength": 1,
       "type": "string"
      },
      "maxItems": 500,
      "title": "Allow",
      "type": "array",
      "description": "Tools allowed (`permissions.allow`)."
     },
     "allow_managed_hooks_only": {
      "default": false,
      "title": "Allow Managed Hooks Only",
      "type": "boolean",
      "description": "Personal, project and plugin hooks are dropped."
     },
     "allow_managed_plugins_only": {
      "default": false,
      "title": "Allow Managed Plugins Only",
      "type": "boolean",
      "description": "Only the plugins of `allowed_plugins` load."
     },
     "allowed_plugins": {
      "items": {
       "maxLength": 200,
       "minLength": 1,
       "type": "string"
      },
      "maxItems": 500,
      "title": "Allowed Plugins",
      "type": "array",
      "description": "Plugins allowed."
     },
     "deny": {
      "items": {
       "maxLength": 200,
       "minLength": 1,
       "type": "string"
      },
      "maxItems": 500,
      "title": "Deny",
      "type": "array",
      "description": "Tools denied (`permissions.deny`)."
     },
     "disable_bypass_permissions": {
      "default": false,
      "title": "Disable Bypass Permissions",
      "type": "boolean",
      "description": "The bypass of the permission prompts is refused."
     },
     "env": {
      "additionalProperties": {
       "maxLength": 4096,
       "type": "string"
      },
      "maxProperties": 100,
      "title": "Env",
      "type": "object",
      "description": "Pinned environment variables; names or values carrying a credential are refused."
     },
     "mcp_allowlist": {
      "anyOf": [
       {
        "items": {
         "maxLength": 200,
         "minLength": 1,
         "type": "string"
        },
        "maxItems": 500,
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Mcp Allowlist",
      "description": "MCP server names allowed; null for no restriction."
     }
    },
    "title": "SmPolicyIn",
    "type": "object"
   },
   "SmtpBody": {
    "additionalProperties": false,
    "properties": {
     "from": {
      "anyOf": [
       {
        "maxLength": 300,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "From",
      "description": "Sender address, for example `<email-address>`."
     },
     "host": {
      "anyOf": [
       {
        "maxLength": 255,
        "pattern": "^[A-Za-z0-9._:-]*$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Host",
      "description": "Host name or address of the SMTP server, for example `<smtp-host>`."
     },
     "password": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Password",
      "description": "Password of the SMTP account: a string sets it, the read back object keeps it. Write only, sealed."
     },
     "port": {
      "anyOf": [
       {
        "maximum": 65535.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Port",
      "description": "Port of the SMTP server, 1 to 65535."
     },
     "starttls": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Starttls",
      "description": "Upgrade the connection with STARTTLS."
     },
     "username": {
      "anyOf": [
       {
        "maxLength": 300,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Username",
      "description": "Account of the SMTP server."
     }
    },
    "title": "SmtpBody",
    "type": "object",
    "description": "Outgoing mail server of the alert notifications."
   },
   "Source": {
    "additionalProperties": false,
    "properties": {
     "chart_path": {
      "anyOf": [
       {
        "maxLength": 253,
        "pattern": "^[A-Za-z0-9][A-Za-z0-9._/-]*$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Chart Path",
      "description": "Path of a chart known to the operator, for example `charts/postgresql`."
     },
     "oci": {
      "anyOf": [
       {
        "maxLength": 512,
        "pattern": "^oci://[A-Za-z0-9.:/_-]+@sha256:[a-f0-9]{64}$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Oci",
      "description": "OCI reference pinned by digest, `oci://<harbor-host>/charts/postgresql@sha256:<64 hex>`."
     }
    },
    "title": "Source",
    "type": "object",
    "description": "Source of a chart: exactly one of `chart_path` and `oci`."
   },
   "SshBootstrapIn": {
    "additionalProperties": false,
    "description": "Machines to connect over SSH (SSH method of adding nodes): the Manager checks the identity of every machine, then runs the same install as the command to paste.",
    "properties": {
     "certificate": {
      "anyOf": [
       {
        "maxLength": 20000,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Certificate",
      "description": "OpenSSH user certificate of the private key (`ssh-ed25519-cert-v01...`), signed by an authority approved in the SSH policy of the cluster. Optional."
     },
     "host_ca": {
      "default": "",
      "maxLength": 2000,
      "title": "Host Ca",
      "type": "string",
      "description": "Public key of the host certificate authority of the machines (`ssh-ed25519 AAAA...`): replaces the identity of each machine when they have host certificates."
     },
     "host_key_fingerprints": {
      "additionalProperties": {
       "type": "string"
      },
      "title": "Host Key Fingerprints",
      "type": "object",
      "description": "First form of the request: expected SSH host key of every host named in `hosts`, as `SHA256:<43 base64 characters>` (output of `ssh-keygen -lf`). A host without a matching fingerprint is refused."
     },
     "hosts": {
      "items": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "$ref": "#/components/schemas/SshMachineIn"
        }
       ]
      },
      "maxItems": 200,
      "minItems": 1,
      "title": "Hosts",
      "type": "array",
      "description": "Machines to connect, 1 to 200: objects `{host, port, host_key}`, or host names with `host_key_fingerprints` (first form)."
     },
     "jumps": {
      "items": {
       "$ref": "#/components/schemas/SshMachineIn"
      },
      "maxItems": 4,
      "title": "Jumps",
      "type": "array",
      "description": "Bastions to cross in order to reach the machines, 4 at most, each one checked by its own identity."
     },
     "passphrase": {
      "anyOf": [
       {
        "maxLength": 1024,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Passphrase",
      "description": "Passphrase of the private key when it is protected. Used by the Manager only to decrypt the key in memory, never sent to a machine nor stored."
     },
     "private_key": {
      "maxLength": 20000,
      "minLength": 20,
      "title": "Private Key",
      "type": "string",
      "description": "SSH private key of `ssh_user` (OpenSSH or PEM): Ed25519, or RSA when the SSH policy of the cluster allows it. Kept in memory for the tasks only, never stored."
     },
     "ssh_port": {
      "default": 22,
      "maximum": 65535.0,
      "minimum": 1.0,
      "title": "Ssh Port",
      "type": "integer",
      "description": "SSH port of the machines without a port of their own, 1 to 65535. Default 22."
     },
     "ssh_user": {
      "maxLength": 32,
      "minLength": 1,
      "title": "Ssh User",
      "type": "string",
      "description": "SSH account with sudo without a password, a Unix user name such as `ec2-user` or `ubuntu`. `root` is refused."
     },
     "use_sudo": {
      "default": true,
      "title": "Use Sudo",
      "type": "boolean",
      "description": "Run the installation with `sudo -n`. Default true."
     }
    },
    "required": [
     "hosts",
     "ssh_user",
     "private_key"
    ],
    "title": "SshBootstrapIn",
    "type": "object"
   },
   "SshMachineIn": {
    "additionalProperties": false,
    "description": "A machine or a bastion of the SSH method.",
    "properties": {
     "host": {
      "maxLength": 253,
      "minLength": 1,
      "title": "Host",
      "type": "string",
      "description": "Name or address of the machine, for example `10.0.1.12` or `<db1-host>`."
     },
     "host_key": {
      "default": "",
      "maxLength": 2000,
      "title": "Host Key",
      "type": "string",
      "description": "Identity of the machine: SHA256 fingerprint of its host key (`SHA256:...`) or its public key line (`ssh-ed25519 AAAA...`). The connection stops when the key differs."
     },
     "port": {
      "anyOf": [
       {
        "maximum": 65535.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Port",
      "description": "SSH port of this machine, 1 to 65535. Default `ssh_port` (22 for a bastion)."
     },
     "user": {
      "default": "",
      "maxLength": 32,
      "title": "User",
      "type": "string",
      "description": "Account on a bastion when it differs from `ssh_user`."
     }
    },
    "required": [
     "host"
    ],
    "title": "SshMachineIn",
    "type": "object"
   },
   "SshPolicyIn": {
    "additionalProperties": false,
    "properties": {
     "allow_rsa": {
      "default": false,
      "title": "Allow Rsa",
      "type": "boolean",
      "description": "Accept RSA keys (Ed25519 is always accepted; DSA and ECDSA never). Default false."
     },
     "approved_user_cas": {
      "items": {
       "type": "string"
      },
      "maxItems": 20,
      "title": "Approved User Cas",
      "type": "array",
      "description": "OpenSSH user CA public keys whose certificates are accepted, at most 20."
     },
     "bootstrap_user": {
      "default": "navin-bootstrap",
      "maxLength": 32,
      "minLength": 1,
      "title": "Bootstrap User",
      "type": "string",
      "description": "Default account of the bootstrap. Default `navin-bootstrap`."
     },
     "rotate_before_days": {
      "default": 30,
      "maximum": 365.0,
      "minimum": 1.0,
      "title": "Rotate Before Days",
      "type": "integer",
      "description": "Days before expiry when an agent certificate is due for rotation, 1 to 365. Default 30."
     },
     "rsa_min_bits": {
      "default": 3072,
      "maximum": 16384.0,
      "minimum": 3072.0,
      "title": "Rsa Min Bits",
      "type": "integer",
      "description": "Smallest RSA key accepted, 3072 to 16384 bits. Default 3072."
     },
     "spiffe_trust_domain": {
      "anyOf": [
       {
        "maxLength": 200,
        "pattern": "^[a-z0-9.-]+$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Spiffe Trust Domain",
      "description": "SPIFFE trust domain of the agent identities, for example `<trust-domain>`; null: none."
     }
    },
    "title": "SshPolicyIn",
    "type": "object",
    "description": "SSH policy of a cluster."
   },
   "SwitchIn": {
    "properties": {
     "to_site": {
      "minLength": 1,
      "title": "To Site",
      "type": "string",
      "description": "Name of the site the traffic goes to."
     }
    },
    "required": [
     "to_site"
    ],
    "title": "SwitchIn",
    "type": "object",
    "description": "Target of a traffic switch."
   },
   "SyslogBody": {
    "additionalProperties": false,
    "properties": {
     "facility": {
      "anyOf": [
       {
        "enum": [
         "kern",
         "user",
         "daemon",
         "auth",
         "authpriv",
         "local0",
         "local1",
         "local2",
         "local3",
         "local4",
         "local5",
         "local6",
         "local7"
        ],
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Facility",
      "description": "Syslog facility: `kern`, `user`, `daemon`, `auth`, `authpriv` or `local0` to `local7`."
     },
     "host": {
      "anyOf": [
       {
        "maxLength": 255,
        "pattern": "^[A-Za-z0-9._:-]*$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Host",
      "description": "Host name or address of the syslog server."
     },
     "port": {
      "anyOf": [
       {
        "maximum": 65535.0,
        "minimum": 1.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Port",
      "description": "Port of the syslog server, 1 to 65535."
     },
     "protocol": {
      "anyOf": [
       {
        "enum": [
         "udp",
         "tcp",
         "tls"
        ],
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Protocol",
      "description": "Transport: `udp`, `tcp` or `tls`."
     }
    },
    "title": "SyslogBody",
    "type": "object",
    "description": "Remote syslog server."
   },
   "TargetsIn": {
    "properties": {
     "rpo_target_seconds": {
      "anyOf": [
       {
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Rpo Target Seconds",
      "description": "Recovery point objective: the largest loss of data accepted, in seconds."
     },
     "rto_target_seconds": {
      "anyOf": [
       {
        "minimum": 0.0,
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Rto Target Seconds",
      "description": "Recovery time objective: the longest time accepted to restore the service, in seconds."
     }
    },
    "title": "TargetsIn",
    "type": "object",
    "description": "Recovery objectives of a DR plan; null clears a target."
   },
   "TokenBody": {
    "additionalProperties": false,
    "properties": {
     "expires_in_days": {
      "default": 90,
      "maximum": 365.0,
      "minimum": 1.0,
      "title": "Expires In Days",
      "type": "integer",
      "description": "Lifetime of the token in days, from 1 to 365. Default 90."
     },
     "name": {
      "maxLength": 100,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Name that tells what the token is for, 1 to 100 characters."
     },
     "permissions": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "maxItems": 32,
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Permissions",
      "description": "Permissions the token is limited to, for example `[\"cluster:read\", \"operations:read\"]`; each must be held by you. Null (default): every permission you hold."
     }
    },
    "required": [
     "name"
    ],
    "title": "TokenBody",
    "type": "object",
    "description": "A new personal API token."
   },
   "TokenIn": {
    "properties": {
     "expires_in_hours": {
      "default": 24,
      "maximum": 720.0,
      "minimum": 1.0,
      "title": "Expires In Hours",
      "type": "integer",
      "description": "Lifetime of the token in hours, 1 to 720. Default 24."
     },
     "max_uses": {
      "default": 50,
      "maximum": 10000.0,
      "minimum": 1.0,
      "title": "Max Uses",
      "type": "integer",
      "description": "Number of agent registrations allowed, 1 to 10000. Default 50."
     }
    },
    "title": "TokenIn",
    "type": "object",
    "description": "Limits of a bootstrap token."
   },
   "TrafficIn": {
    "properties": {
     "kind": {
      "title": "Kind",
      "type": "string",
      "description": "Kind of switch: `dns` or `load_balancer`."
     },
     "name": {
      "maxLength": 200,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Name of the record or load balancer, 1 to 200 characters, for example `<app-host>`."
     },
     "spec": {
      "additionalProperties": true,
      "title": "Spec",
      "type": "object",
      "description": "Specification: `sites` (value per site) and `health_check` with its `url`, both required."
     }
    },
    "required": [
     "kind",
     "name",
     "spec"
    ],
    "title": "TrafficIn",
    "type": "object",
    "description": "A DNS record or load balancer switched by a DR plan."
   },
   "TrustIn": {
    "properties": {
     "reason": {
      "default": "",
      "maxLength": 500,
      "title": "Reason",
      "type": "string",
      "description": "Why the trust state changes, at most 500 characters; redacted and audited."
     }
    },
    "title": "TrustIn",
    "type": "object",
    "description": "Reason of a trust state change."
   },
   "UpdateIn": {
    "properties": {
     "health_timeout_s": {
      "default": 120,
      "maximum": 900.0,
      "minimum": 30.0,
      "title": "Health Timeout S",
      "type": "integer",
      "description": "Seconds the new agent has to report healthy after the update, 30 to 900. Default 120."
     },
     "ttl_s": {
      "default": 900,
      "maximum": 3600.0,
      "minimum": 60.0,
      "title": "Ttl S",
      "type": "integer",
      "description": "Validity of the command in seconds, 60 to 3600. Default 900."
     }
    },
    "title": "UpdateIn",
    "type": "object",
    "description": "Options of an agent update."
   },
   "UpgradeBody": {
    "properties": {
     "approval_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approval Id",
      "description": "Identifier of the approved request (four-eyes approval) that authorizes this action."
     },
     "auto_rollback": {
      "default": false,
      "title": "Auto Rollback",
      "type": "boolean",
      "description": "true: when the upgrade fails, the Manager at once replays the previous release, sealed before the upgrade ran, without asking for a new approval (the approval of the upgrade covers it). The security lock, the modes and the profile of the cluster still decide. When the rollback is impossible (irreversible migration, rollback not supported by the catalog, operation refused), the upgrade stays failed, the reason is audited and the way back is the restore of the backup taken before the upgrade. Default false: a failed upgrade waits for the operator."
     },
     "canary_host": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Canary Host",
      "description": "Host upgraded first (the canary); null: the first host of the service."
     }
    },
    "title": "UpgradeBody",
    "type": "object",
    "description": "Options of an upgrade."
   },
   "UserCreate": {
    "additionalProperties": false,
    "properties": {
     "display_name": {
      "default": "",
      "maxLength": 200,
      "title": "Display Name",
      "type": "string",
      "description": "Name shown in the console; the username when empty."
     },
     "email": {
      "default": "",
      "maxLength": 200,
      "pattern": "^$|^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$",
      "title": "Email",
      "type": "string",
      "description": "Email address of the user; may be empty."
     },
     "language": {
      "default": "en",
      "enum": [
       "en",
       "fr"
      ],
      "title": "Language",
      "type": "string",
      "description": "Language of the console: `en` (default) or `fr`."
     },
     "must_change_password": {
      "default": true,
      "title": "Must Change Password",
      "type": "boolean",
      "description": "When true (default), the user must choose a new password at the first sign in."
     },
     "password": {
      "maxLength": 1024,
      "minLength": 1,
      "title": "Password",
      "type": "string",
      "description": "Initial password; must follow the password policy. Write only."
     },
     "roles": {
      "items": {
       "$ref": "#/components/schemas/RoleItem"
      },
      "maxItems": 50,
      "title": "Roles",
      "type": "array",
      "description": "Initial role bindings, at most 50."
     },
     "username": {
      "maxLength": 100,
      "minLength": 1,
      "pattern": "^[A-Za-z0-9._@-]+$",
      "title": "Username",
      "type": "string",
      "description": "Unique username, case insensitive: letters, digits, `.`, `_`, `@` and `-`, at most 100 characters."
     }
    },
    "required": [
     "username",
     "password"
    ],
    "title": "UserCreate",
    "type": "object",
    "description": "A new local user."
   },
   "UserPatch": {
    "additionalProperties": false,
    "properties": {
     "disabled": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Disabled",
      "description": "True disables the account (its sessions are revoked), false enables it again."
     },
     "display_name": {
      "anyOf": [
       {
        "maxLength": 200,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Display Name",
      "description": "Name shown in the console, at most 200 characters."
     },
     "email": {
      "anyOf": [
       {
        "maxLength": 200,
        "pattern": "^$|^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Email",
      "description": "Email address, at most 200 characters."
     },
     "language": {
      "anyOf": [
       {
        "enum": [
         "en",
         "fr"
        ],
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Language",
      "description": "Language of the console: `en` or `fr`."
     },
     "must_change_password": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Must Change Password",
      "description": "When true, the user must choose a new password at the next sign in."
     }
    },
    "title": "UserPatch",
    "type": "object",
    "description": "Change of a user; a field left out or null is kept."
   },
   "ValidateBody": {
    "properties": {
     "blueprint": {
      "additionalProperties": true,
      "title": "Blueprint",
      "type": "object",
      "description": "The blueprint document, schema `navin-manager/blueprint/v1`."
     },
     "host_mapping": {
      "anyOf": [
       {
        "additionalProperties": {
         "items": {
          "type": "string"
         },
         "type": "array"
        },
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Host Mapping",
      "description": "Hosts of the target cluster for each host group, as `{group name: [host ids or FQDNs]}`. Null: only the shape is checked."
     }
    },
    "required": [
     "blueprint"
    ],
    "title": "ValidateBody",
    "type": "object",
    "description": "A blueprint to validate."
   },
   "ValidationError": {
    "properties": {
     "ctx": {
      "title": "Context",
      "type": "object",
      "description": "Context of the rule that failed, for example the bound that was exceeded."
     },
     "input": {
      "title": "Input",
      "description": "Value that was refused."
     },
     "loc": {
      "items": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "integer"
        }
       ]
      },
      "title": "Location",
      "type": "array",
      "description": "Location of the item: `body`, `query` or `path`, then the field names."
     },
     "msg": {
      "title": "Message",
      "type": "string",
      "description": "Human readable message."
     },
     "type": {
      "title": "Error Type",
      "type": "string",
      "description": "Code of the rule that failed, for example `missing` or `string_too_long`."
     }
    },
    "required": [
     "loc",
     "msg",
     "type"
    ],
    "title": "ValidationError",
    "type": "object",
    "description": "One invalid item of a request, as declared by FastAPI."
   },
   "VerifyBody": {
    "properties": {
     "document": {
      "additionalProperties": true,
      "title": "Document",
      "type": "object",
      "description": "The report document as returned by the API, signature included."
     }
    },
    "required": [
     "document"
    ],
    "title": "VerifyBody",
    "type": "object",
    "description": "A signed acceptance report to verify."
   },
   "navin_manager__agentapi__node__EnrollIn": {
    "properties": {
     "agent_version": {
      "default": "",
      "maxLength": 40,
      "title": "Agent Version",
      "type": "string"
     },
     "csr_pem": {
      "maxLength": 20000,
      "minLength": 100,
      "title": "Csr Pem",
      "type": "string"
     },
     "enrollment_token": {
      "maxLength": 200,
      "minLength": 20,
      "title": "Enrollment Token",
      "type": "string"
     },
     "facts": {
      "additionalProperties": true,
      "title": "Facts",
      "type": "object"
     },
     "fqdn": {
      "maxLength": 253,
      "minLength": 1,
      "title": "Fqdn",
      "type": "string",
      "description": "Fully qualified domain name of the host, for example `<db1-host>`."
     },
     "hostname": {
      "maxLength": 253,
      "minLength": 1,
      "title": "Hostname",
      "type": "string"
     },
     "ip": {
      "default": "",
      "maxLength": 64,
      "title": "Ip",
      "type": "string"
     },
     "service_driver": {
      "default": "systemd",
      "pattern": "^(systemd|process)$",
      "title": "Service Driver",
      "type": "string"
     }
    },
    "required": [
     "enrollment_token",
     "hostname",
     "fqdn",
     "csr_pem"
    ],
    "title": "EnrollIn",
    "type": "object"
   },
   "navin_manager__api__alerts__TargetIn": {
    "properties": {
     "config": {
      "additionalProperties": true,
      "title": "Config",
      "type": "object",
      "description": "Settings of the kind: `{\"to\": \"<email-address>\"}` for `email`, `{\"url\": \"https://<hooks-host>/navin\"}` for `webhook`."
     },
     "enabled": {
      "default": true,
      "title": "Enabled",
      "type": "boolean",
      "description": "Whether the target receives notifications. Default true."
     },
     "hmac_secret": {
      "title": "Hmac Secret",
      "description": "Secret that signs the webhook bodies (`X-NM-Signature`). Write only, sealed at rest."
     },
     "kind": {
      "enum": [
       "email",
       "webhook",
       "syslog"
      ],
      "title": "Kind",
      "type": "string",
      "description": "Kind of target: `email`, `webhook` or `syslog`."
     },
     "min_severity": {
      "default": "warning",
      "enum": [
       "warning",
       "critical"
      ],
      "title": "Min Severity",
      "type": "string",
      "description": "Lowest severity notified: `warning` (default) or `critical`. Resolutions are notified too."
     },
     "name": {
      "maxLength": 120,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Name of the target, 1 to 120 characters."
     },
     "params": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Params"
     }
    },
    "required": [
     "name",
     "kind"
    ],
    "title": "TargetIn",
    "type": "object",
    "description": "A new notification target."
   },
   "navin_manager__api__alerts__TargetPatch": {
    "properties": {
     "config": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Config",
      "description": "New settings of the kind."
     },
     "enabled": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Enabled",
      "description": "Whether the target receives notifications."
     },
     "hmac_secret": {
      "title": "Hmac Secret",
      "description": "New HMAC secret: a string sets it, an empty string removes it, null or the read back object keeps it."
     },
     "min_severity": {
      "enum": [
       "warning",
       "critical",
       null
      ],
      "title": "Min Severity",
      "description": "Lowest severity notified: `warning` or `critical`."
     },
     "name": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name",
      "description": "New name of the target."
     },
     "params": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Params"
     }
    },
    "title": "TargetPatch",
    "type": "object",
    "description": "Change of a notification target; a field left out or null is kept."
   },
   "navin_manager__api__backup_recovery__TargetIn": {
    "properties": {
     "bucket": {
      "minLength": 1,
      "title": "Bucket",
      "type": "string",
      "description": "Bucket or container; for `filesystem`, the root directory."
     },
     "capabilities": {
      "additionalProperties": true,
      "default": {},
      "title": "Capabilities",
      "type": "object",
      "description": "Capabilities of the target, for example verified `object_lock` and `retention` for immutable backups."
     },
     "endpoint": {
      "default": "",
      "title": "Endpoint",
      "type": "string",
      "description": "Address of the storage service, for example `https://<s3-host>`; empty for `filesystem`."
     },
     "name": {
      "maxLength": 100,
      "minLength": 1,
      "title": "Name",
      "type": "string",
      "description": "Name of the target, 1 to 100 characters."
     },
     "provider": {
      "title": "Provider",
      "type": "string",
      "description": "Provider: `s3`, `azure_blob`, `gcs`, `ibm_cos`, `seaweedfs` or `filesystem`."
     },
     "purpose": {
      "default": "backup",
      "title": "Purpose",
      "type": "string",
      "description": "Use of the target. Default `backup`."
     },
     "secret_ref": {
      "default": "",
      "title": "Secret Ref",
      "type": "string",
      "description": "Reference of the credentials of the storage, never the secret itself."
     }
    },
    "required": [
     "name",
     "provider",
     "bucket"
    ],
    "title": "TargetIn",
    "type": "object",
    "description": "A backup target."
   },
   "navin_manager__api__blueprint__ApplyBody": {
    "properties": {
     "blueprint": {
      "additionalProperties": true,
      "title": "Blueprint",
      "type": "object",
      "description": "The blueprint document, schema `navin-manager/blueprint/v1`."
     },
     "ha_acknowledged": {
      "default": false,
      "title": "Ha Acknowledged",
      "type": "boolean",
      "description": "Accept a topology below the high availability requirements. Default false."
     },
     "host_mapping": {
      "additionalProperties": {
       "items": {
        "type": "string"
       },
       "type": "array"
      },
      "title": "Host Mapping",
      "type": "object",
      "description": "Hosts of the target cluster for each host group, as `{group name: [host ids or FQDNs]}`; every group must be mapped."
     },
     "service_check": {
      "default": true,
      "title": "Service Check",
      "type": "boolean",
      "description": "Run the service checks at the end. Default true."
     },
     "start": {
      "default": true,
      "title": "Start",
      "type": "boolean",
      "description": "Start the services once installed. Default true."
     }
    },
    "required": [
     "blueprint"
    ],
    "title": "ApplyBody",
    "type": "object",
    "description": "A blueprint to apply."
   },
   "navin_manager__api__configs__ApplyBody": {
    "properties": {
     "approval_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approval Id",
      "description": "Approval granted for this apply under `banking-secure`."
     },
     "batch_size": {
      "default": 1,
      "maximum": 100.0,
      "minimum": 1.0,
      "title": "Batch Size",
      "type": "integer",
      "description": "Hosts restarted at the same time by a rolling restart, 1 to 100. Default 1."
     },
     "restart": {
      "default": "rolling",
      "enum": [
       "rolling",
       "all",
       "none"
      ],
      "title": "Restart",
      "type": "string",
      "description": "Restart policy: `rolling` (default, `batch_size` hosts at a time), `all` (every instance at once) or `none` (files only)."
     }
    },
    "title": "ApplyBody",
    "type": "object",
    "description": "How to apply the configuration."
   },
   "navin_manager__api__connections__ConnectionPatch": {
    "additionalProperties": false,
    "properties": {
     "description": {
      "anyOf": [
       {
        "maxLength": 1000,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description",
      "description": "New description."
     },
     "name": {
      "anyOf": [
       {
        "maxLength": 100,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name",
      "description": "New unique name."
     },
     "params": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Params",
      "description": "New parameters of the type, checked again."
     },
     "secret": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Secret",
      "description": "New secret: a string sets it, the read back object or null keeps it."
     }
    },
    "title": "ConnectionPatch",
    "type": "object",
    "description": "Change of a connection; a field left out or null is kept."
   },
   "navin_manager__api__k8s_agents__CommandIn": {
    "additionalProperties": false,
    "properties": {
     "idempotency_key": {
      "maxLength": 128,
      "minLength": 8,
      "title": "Idempotency Key",
      "type": "string",
      "description": "Key that makes a retry return the same command, 8 to 128 characters; generated when omitted."
     },
     "operation": {
      "enum": [
       "managedcomponent.apply",
       "managedcomponent.delete",
       "inventory.report"
      ],
      "title": "Operation",
      "type": "string",
      "description": "`managedcomponent.apply`, `managedcomponent.delete` or `inventory.report`."
     },
     "parameters": {
      "additionalProperties": true,
      "title": "Parameters",
      "type": "object",
      "description": "Parameters of the operation."
     },
     "trace_id": {
      "anyOf": [
       {
        "maxLength": 64,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Trace Id",
      "description": "Trace identifier carried to the receipts, at most 64 characters."
     },
     "ttl_s": {
      "default": 600,
      "maximum": 3600.0,
      "minimum": 30.0,
      "title": "Ttl S",
      "type": "integer",
      "description": "Validity of the command in seconds, 30 to 3600. Default 600."
     }
    },
    "required": [
     "operation"
    ],
    "title": "CommandIn",
    "type": "object",
    "description": "A signed command for the cluster agent."
   },
   "navin_manager__api__kubernetes__TargetIn": {
    "additionalProperties": false,
    "properties": {
     "api_server": {
      "maxLength": 512,
      "minLength": 8,
      "title": "Api Server",
      "type": "string",
      "description": "HTTPS address of the API server, for example `<api-server-url>`; the kubeconfig must point at it."
     },
     "kubeconfig": {
      "maxLength": 262144,
      "minLength": 1,
      "title": "Kubeconfig",
      "type": "string",
      "description": "Kubeconfig of the import identity. Write only, sealed at rest."
     },
     "namespace": {
      "default": "navin-platform",
      "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
      "title": "Namespace",
      "type": "string",
      "description": "Managed namespace. Default `navin-platform`."
     }
    },
    "required": [
     "api_server",
     "kubeconfig"
    ],
    "title": "TargetIn",
    "type": "object",
    "description": "A Kubernetes cluster to register."
   },
   "navin_manager__api__kubernetes__TargetPatch": {
    "additionalProperties": false,
    "properties": {
     "api_server": {
      "anyOf": [
       {
        "maxLength": 512,
        "minLength": 8,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Api Server",
      "description": "New API server address."
     },
     "kubeconfig": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Kubeconfig",
      "description": "New kubeconfig; null or the read back object keeps the stored one."
     },
     "namespace": {
      "anyOf": [
       {
        "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Namespace",
      "description": "New managed namespace; refused while components remain."
     }
    },
    "title": "TargetPatch",
    "type": "object",
    "description": "Change of a Kubernetes target; a field left out is kept."
   },
   "navin_manager__api__node_security__CommandIn": {
    "additionalProperties": false,
    "properties": {
     "idempotency_key": {
      "anyOf": [
       {
        "maxLength": 100,
        "minLength": 8,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Idempotency Key",
      "description": "Key that makes a retry return the same command, 8 to 100 characters."
     },
     "operation": {
      "maxLength": 60,
      "minLength": 1,
      "title": "Operation",
      "type": "string",
      "description": "Operation: `facts.collect`, `health.check`, `logs.tail`, `files.digest`, `service.control`, `command.run` or `agent.update`."
     },
     "parameters": {
      "additionalProperties": true,
      "title": "Parameters",
      "type": "object",
      "description": "Parameters of the operation."
     },
     "trace_id": {
      "anyOf": [
       {
        "maxLength": 100,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Trace Id",
      "description": "Trace identifier carried to the receipt, at most 100 characters."
     },
     "ttl_s": {
      "default": 300,
      "maximum": 3600.0,
      "minimum": 30.0,
      "title": "Ttl S",
      "type": "integer",
      "description": "Validity of the command in seconds, 30 to 3600. Default 300."
     }
    },
    "required": [
     "operation"
    ],
    "title": "CommandIn",
    "type": "object",
    "description": "A signed command for a node agent."
   },
   "navin_manager__api__node_security__EnrollIn": {
    "additionalProperties": false,
    "properties": {
     "cluster_id": {
      "title": "Cluster Id",
      "type": "string"
     },
     "fqdn": {
      "maxLength": 253,
      "minLength": 1,
      "title": "Fqdn",
      "type": "string",
      "description": "Fully qualified domain name of the host, for example `<db1-host>`."
     },
     "host_fingerprint": {
      "maxLength": 100,
      "minLength": 64,
      "title": "Host Fingerprint",
      "type": "string"
     },
     "ttl_s": {
      "default": 600,
      "maximum": 900.0,
      "minimum": 60.0,
      "title": "Ttl S",
      "type": "integer"
     }
    },
    "required": [
     "cluster_id",
     "fqdn",
     "host_fingerprint"
    ],
    "title": "EnrollIn",
    "type": "object"
   },
   "navin_manager__api__services__ConnectionPatch": {
    "additionalProperties": false,
    "description": "Change of a connected service: a value left out keeps the stored one, a secret field left empty too.",
    "properties": {
     "auth": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/ConnectAuth"
       },
       {
        "type": "null"
       }
      ],
      "description": "New authentication method or fields (credential rotation)."
     },
     "ca_pem": {
      "anyOf": [
       {
        "maxLength": 65536,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Ca Pem",
      "description": "New certificate authority, PEM."
     },
     "config": {
      "anyOf": [
       {
        "additionalProperties": true,
        "maxProperties": 100,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Config",
      "description": "New values of the configuration keys."
     },
     "credentials_ref": {
      "anyOf": [
       {
        "maxLength": 512,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Credentials Ref",
      "description": "New reference to external credentials (URI)."
     },
     "dry_run": {
      "default": false,
      "title": "Dry Run",
      "type": "boolean",
      "description": "Only check the change, do not save it. Default false."
     },
     "endpoint": {
      "anyOf": [
       {
        "maxLength": 2048,
        "minLength": 1,
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Endpoint",
      "description": "New address of the service."
     },
     "mtls": {
      "anyOf": [
       {
        "$ref": "#/components/schemas/ClientCertificate"
       },
       {
        "type": "null"
       }
      ],
      "description": "New client certificate; an empty object removes it."
     },
     "tls_verify": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tls Verify",
      "description": "Verify the TLS certificate of the service."
     }
    },
    "title": "ConnectionPatch",
    "type": "object"
   }
  }
 },
 "info": {
  "title": "Navin Manager API",
  "version": "1.0.2",
  "description": "## Overview\n\nThe Navin Manager is the management console of the Navin platform. Its REST API is the one the web console uses:\neverything you do in the console, you can do with this API. It manages:\n\n- **clusters**: an environment of hosts (or a Kubernetes cluster) with its mode (production, test,\n  sandbox...), its installation profile (standard, banking-secure, air-gapped...), its settings and its services;\n- **hosts**: machines registered by their Navin agent, with their facts, metrics, preflight checks and parameters;\n- **services**: catalog services (PostgreSQL, Keycloak, Kafka...) installed on the hosts, or existing services\n  connected to the Manager, with their components, configuration versions, client configuration and dashboards;\n- **operations**: every change (install, restart, upgrade, backup...) runs as an operation made of stages and\n  tasks executed by the agents of the hosts;\n- **security, backup and lifecycle**: users and roles, identity providers, PKI, vault, node security, backups,\n  restores, disaster recovery, upgrades and approvals.\n\n## Base URL and versioning\n\nEvery endpoint is served under `/api/v1` on the console listener of the Manager, for example\n`<manager-url>/api/v1/clusters`. The version is part of the path: a change that breaks a client\ngets a new version prefix; fields may be added to a response of `/api/v1` at any time, so clients must ignore the\nfields they do not know. The OpenAPI document is served at `/api/v1/openapi.json`. Bodies are JSON (UTF-8); dates\nare ISO 8601 with a time zone; identifiers are UUIDs given as strings.\n\n## Authentication\n\nA request is authenticated in one of two ways:\n\n1. **Session cookie** (the web console). `POST /api/v1/auth/login` with a username and a password (local account\n   or LDAP) opens a server side session stored in the `nm_session` cookie (HttpOnly, idle and absolute timeouts)\n   and returns a `csrf_token`. Every unsafe request (`POST`, `PUT`, `PATCH`, `DELETE`) made with the cookie must\n   send this value in the `X-CSRF-Token` header, else it is refused with `403 csrf_invalid`. OIDC sign in starts\n   with `GET /api/v1/auth/oidc/{provider_id}/start`.\n2. **API token** (scripts, CI, integrations). Create a personal token from your profile in the console, or with\n   `POST /api/v1/me/tokens` from a browser session. A token looks like `nmt_<12 hex>_<secret>`, is shown once,\n   expires (90 days by default, at most 365) and can be restricted to a subset of your permissions. Send it in the\n   `Authorization` header; no CSRF header is needed:\n\n```bash\ncurl -H \"Authorization: Bearer <token>\" <manager-url>/api/v1/clusters\n```\n\n**Second factor (MFA).** When the Manager runs with TOTP enabled, a login whose account has MFA (or whose role\nrequires it) answers `{\"mfa_required\": true, \"mfa_token\": ...}` instead of a session; finish it with\n`POST /api/v1/auth/mfa/verify` (or enroll first with `/auth/mfa/enroll/start` and `/auth/mfa/enroll/confirm`).\nCredentials, MFA and tokens are managed from a browser session only: an API token cannot create another token.\n\nMissing or invalid credentials give `401` (`unauthenticated`, `session_expired`, `token_invalid`); repeated\nfailures give `429 too_many_attempts` with a `Retry-After` header, then `423 account_locked`.\n\n## Permissions\n\nAccess is role based. A user holds role bindings, each global or limited to one cluster: `admin`,\n`security_admin`, `cluster_admin`, `operator`, `viewer`, `auditor`. A role grants permission strings such as\n`cluster:read`, `services:install`, `services:operate`, `configs:edit`, `operations:abort`, `alerts:manage`,\n`audit:read`, `users:manage`, `backup:manage`, `restore:execute`, `vault:manage` or `mcp:manage`. Some\npermissions are global only (`users:manage`, `audit:read`, `settings:manage`, `pki:manage`...): a cluster scoped\nbinding never grants them. Each operation of this reference names the permission it checks; for a cluster path the\npermission may be held globally or on that cluster. `GET /api/v1/auth/session` returns the effective permissions\nof the caller. A refusal answers `403 permission_denied` with the missing permission in `details` and is written\nto the audit trail.\n\n## Errors\n\nEvery error has the same envelope, with the message in the language of the caller (cookie `nm_lang`, then\n`Accept-Language`) and in both languages:\n\n```json\n{\n  \"error\": {\n    \"code\": \"permission_denied\",\n    \"message\": \"You do not have the permission services:install.\",\n    \"message_i18n\": {\n      \"en\": \"You do not have the permission services:install.\",\n      \"fr\": \"Vous n'avez pas la permission services:install.\"\n    },\n    \"details\": {\"permission\": \"services:install\", \"cluster_id\": \"6f1c2b9e-0000-4000-8000-000000000001\"}\n  }\n}\n```\n\nTest `code`, never the message. Common codes:\n\n| HTTP | Code | Meaning |\n|------|------|---------|\n| 401 | `unauthenticated`, `session_expired`, `token_invalid` | No valid session or token. |\n| 403 | `permission_denied`, `csrf_invalid`, `session_required` | Permission missing, CSRF header missing, or the call needs a browser session. |\n| 404 | `not_found`, `cluster_not_found`, `operation_not_found`... | The resource does not exist or is not visible. |\n| 409 | `profile_blocked`, `approval_required`, `service_in_use`... | The current state or the profile of the cluster refuses the action. |\n| 422 | `validation_error` | The body or a parameter is invalid; `details.fields` maps each field to its `code` and `message`. |\n| 429 | `too_many_attempts` | Rate limit; wait the seconds of `Retry-After`. |\n| 500 | `internal_error` | Unexpected error; `details.incident` identifies it in the server logs. |\n\nEvery response carries an `X-Request-Id` header (the one you sent, or a new one) to quote when you report a problem.\n\n## Pagination\n\nLists answer `{\"items\": [...], \"next_cursor\": ...}`. When a list is paginated it accepts `limit` (bounded by the\nserver) and `cursor`: pass the `next_cursor` of a page as `cursor` to read the next one; `next_cursor` is `null` on\nthe last page. Many lists of a cluster are small and always return everything with `next_cursor: null`.\n\n## Asynchronous operations\n\nA change is not made during the request: the API validates it, plans it and answers at once with an\n`operation_id`. For example, installing services:\n\n1. `POST /api/v1/clusters/{cluster_id}/services/validate` checks the request (errors, high availability, missing\n   dependencies) and shows the plan, without changing anything;\n2. `POST /api/v1/clusters/{cluster_id}/services` creates the operation and returns `{\"operation_id\": ...}`;\n3. `GET /api/v1/operations/{operation_id}` returns its `status` (`pending`, `running`, `succeeded`, `failed`,\n   `aborted`), its `progress` and its stages, each with one task per host;\n4. `GET /api/v1/operations/{operation_id}/tasks/{task_id}/logs` streams the output of a task (`after_seq`);\n5. `POST /api/v1/operations/{operation_id}/abort` stops it, `POST /api/v1/operations/{operation_id}/retry` runs a\n   failed or aborted one again.\n\nUnder the `banking-secure` profile a disruptive operation (uninstall, restore...) also needs the approval of a\nsecond person: request it, have it approved, then send its `approval_id` (or let the Manager find the approval\ngranted to you); without it the API answers `409 approval_required`.\n\n## Audit\n\nEvery change, every sign in and every refusal is written to a tamper evident audit trail (each event is chained\nto the previous one by a hash) with the actor, the target, the cluster, the outcome and the client address.\nReaders with `audit:read` list it with `GET /api/v1/audit`, verify the chain with `GET /api/v1/audit/verify` and\nexport it as NDJSON or CSV. Secrets are never written to the audit trail.\n\n## Agent endpoints\n\nThe Navin agents talk to the Manager on a separate listener protected by mutual TLS (heartbeats, task polling,\nresults, packages). That channel is not part of this API. Only the registration of a new agent,\n`POST /agent/v1/register`, is documented here, under **Agent**."
 },
 "openapi": "3.1.0",
 "paths": {
  "/agent/v1/enroll": {
   "post": {
    "description": "Enrollment (HOST-011): the token is consumed by the first CSR of the bound key, then the host registers like\nwith a bootstrap token (one use, one minute) and receives its mTLS identity.",
    "operationId": "enroll_agent_v1_enroll_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__agentapi__node__EnrollIn"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Enroll Agent V1 Enroll Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Enroll",
    "tags": [
     "agent"
    ]
   }
  },
  "/agent/v1/register": {
   "post": {
    "operationId": "register_agent_v1_register_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RegisterIn"
       }
      }
     },
     "required": true,
     "description": "Bootstrap token, names, facts and CSR of the agent."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Register Agent V1 Register Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Register an agent with a bootstrap token",
    "tags": [
     "agent"
    ],
    "description": "Registers the agent of a host in the cluster of the bootstrap token and signs its client certificate.\n\nA host already known with the same FQDN in the same cluster is registered again: it gets a new secret and a\nnew certificate, its previous certificates are revoked. The use counter of the token is incremented.\n\nThe response gives `host_id`, `cluster_id`, `agent_secret`, `certificate_pem`, `ca_pem` and its SHA-256\nfingerprint `ca_sha256`, the public keys that sign commands and packages (`command_key_pem`,\n`package_key_pem`), the `spiffe_id`, the URLs of the agent listener and of the mirror, and the polling\nintervals (`heartbeat_interval_s`, `poll_wait_s`).\n\nErrors: `401 bootstrap_token_invalid` (unknown, revoked, expired or used up), `409 host_in_other_cluster` (the\nFQDN belongs to a host of another cluster that is not decommissioned), `422 csr_invalid`,\n`422 validation_error` (FQDN not a valid DNS name). Audited as `host.register` or `host.reregister`."
   }
  },
  "/api/v1/acceptance/public-key": {
   "get": {
    "operationId": "acceptance_key_api_v1_acceptance_public_key_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Acceptance Key Api V1 Acceptance Public Key Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the public key that signs the acceptance reports",
    "tags": [
     "lifecycle"
    ],
    "description": "Returns `algorithm` (`Ed25519`), `key_id` and `public_key_pem`, to verify a report offline. Any signed in user."
   }
  },
  "/api/v1/acceptance/verify": {
   "post": {
    "operationId": "verify_report_api_v1_acceptance_verify_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/VerifyBody"
       }
      }
     },
     "required": true,
     "description": "The signed report document."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Verify Report Api V1 Acceptance Verify Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Verify the signature of an acceptance report",
    "tags": [
     "lifecycle"
    ],
    "description": "Checks the Ed25519 signature of a report document against the key of this Manager and returns `valid`, `trusted`, `key_id` and the `reason` of a refusal. Any signed in user."
   }
  },
  "/api/v1/agent-templates": {
   "get": {
    "description": "Every agent template of the registry, sorted by identifier, with `published` computed against the loaded catalog and the publications of this Manager, `reason` (fr and en) when it cannot be deployed, `publication` (version, who, when) when it was published here, `publishable` and `publish_blocker`. Returns `items` and `count`. Any signed in user.",
    "operationId": "agent_templates_api_v1_agent_templates_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Agent Templates Api V1 Agent Templates Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the agent templates",
    "tags": [
     "agent-templates"
    ]
   }
  },
  "/api/v1/agent-templates/{template_id}": {
   "get": {
    "description": "One agent template by its identifier: name and description (fr and en), publisher, version, status, catalog service, documentation and source paths, components, `published`, `reason`, `publication`, `publishable` and `publish_blocker`. Any signed in user; `404` for an unknown template.",
    "operationId": "agent_template_api_v1_agent_templates__template_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "template_id",
      "required": true,
      "schema": {
       "title": "Template Id",
       "type": "string"
      },
      "description": "Identifier of the agent template, equal to the name of its descriptor file."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Agent Template Api V1 Agent Templates  Template Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get an agent template",
    "tags": [
     "agent-templates"
    ]
   }
  },
  "/api/v1/agent-templates/{template_id}/publication": {
   "delete": {
    "description": "Removes the service definition and the templates published on this Manager and the publication record: the service leaves the catalog and the template is awaiting validation again. Refused while an instance of the service is installed in a cluster (`409 agent_template_in_use`, the instances are in `details.instances`). Returns the template. Permission `agent_templates:publish`; audited as `agent_template.unpublish`. Errors: `404 agent_template_unknown`, `404 agent_template_not_published`.",
    "operationId": "withdraw_agent_template_api_v1_agent_templates__template_id__publication_delete",
    "parameters": [
     {
      "in": "path",
      "name": "template_id",
      "required": true,
      "schema": {
       "title": "Template Id",
       "type": "string"
      },
      "description": "Identifier of the agent template."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Withdraw Agent Template Api V1 Agent Templates  Template Id  Publication Delete",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Withdraw the publication of an agent template",
    "tags": [
     "agent-templates"
    ]
   }
  },
  "/api/v1/agent-templates/{template_id}/publish": {
   "post": {
    "description": "The validation of the customer: the service definition and the templates of the agent are checked by the catalog loader together with the whole catalog (on a staging copy, nothing is written when a check fails), then copied under `published_templates_dir`; the service joins the catalog of this Manager, the template answers `published: true` and its Deploy button opens the install wizard. Publishing again replaces the files with the current sources. Returns the template. Permission `agent_templates:publish`; audited as `agent_template.publish`. Errors: `404 agent_template_unknown`, `409 agent_template_not_publishable` (planned or in development), `409 agent_template_sources_missing`, `409 agent_template_already_published` (service shipped with the catalog), `422 agent_template_invalid` (the problems found are in `details.problems`).",
    "operationId": "publish_agent_template_api_v1_agent_templates__template_id__publish_post",
    "parameters": [
     {
      "in": "path",
      "name": "template_id",
      "required": true,
      "schema": {
       "title": "Template Id",
       "type": "string"
      },
      "description": "Identifier of the agent template."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Publish Agent Template Api V1 Agent Templates  Template Id  Publish Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Validate and publish an agent template",
    "tags": [
     "agent-templates"
    ]
   }
  },
  "/api/v1/agents/nodes": {
   "get": {
    "operationId": "list_nodes_api_v1_agents_nodes_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Nodes Api V1 Agents Nodes Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the node agents",
    "tags": [
     "node-security"
    ],
    "description": "Hosts not decommissioned of every cluster the caller may read, with their trust state, management mode, agent version, last heartbeat, identity (certificate serial and expiry, SPIFFE ID, `rotation_due`), metrics and platform."
   }
  },
  "/api/v1/agents/nodes/{host_id}": {
   "get": {
    "operationId": "node_detail_api_v1_agents_nodes__host_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Node Detail Api V1 Agents Nodes  Host Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a node agent",
    "tags": [
     "node-security"
    ],
    "description": "The node view plus its last 10 `certificates` and `diagnostics` (facts, last metrics, last 20 receipts). Permission `cluster:read`; `404 host_not_found`."
   }
  },
  "/api/v1/alert-definitions": {
   "get": {
    "operationId": "list_definitions_api_v1_alert_definitions_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Definitions Api V1 Alert Definitions Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the alert definitions",
    "tags": [
     "alerts"
    ],
    "description": "Every definition with its `name`, `scope`, `kind`, `label`, `description`, `enabled`, `interval_s`, `warning` and `critical` thresholds and `params`. Permission `alerts:read`."
   }
  },
  "/api/v1/alert-definitions/{definition_id}": {
   "patch": {
    "operationId": "patch_definition_api_v1_alert_definitions__definition_id__patch",
    "parameters": [
     {
      "in": "path",
      "name": "definition_id",
      "required": true,
      "schema": {
       "title": "Definition Id",
       "type": "string"
      },
      "description": "Identifier of the alert definition."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DefinitionPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the definition to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Patch Definition Api V1 Alert Definitions  Definition Id  Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Tune an alert definition",
    "tags": [
     "alerts"
    ],
    "description": "Turns a definition on or off and changes its thresholds or its evaluation interval; a field left out is kept. Returns the definition. Permission `alerts:manage`; `404 alert_definition_not_found`. Audited as `alert_definition.update`."
   }
  },
  "/api/v1/alerts/{alert_id}": {
   "get": {
    "operationId": "get_alert_api_v1_alerts__alert_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "alert_id",
      "required": true,
      "schema": {
       "title": "Alert Id",
       "type": "string"
      },
      "description": "Identifier of the alert."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Alert Api V1 Alerts  Alert Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get an alert",
    "tags": [
     "alerts"
    ],
    "description": "Returns one alert with the `history` of its state changes (the last 200: `ts`, `from_state`, `to_state`, `value`, `text`). Permission `alerts:read` on its cluster; `404 alert_not_found`."
   }
  },
  "/api/v1/alerts/{alert_id}/ack": {
   "post": {
    "operationId": "ack_alert_api_v1_alerts__alert_id__ack_post",
    "parameters": [
     {
      "in": "path",
      "name": "alert_id",
      "required": true,
      "schema": {
       "title": "Alert Id",
       "type": "string"
      },
      "description": "Identifier of the alert."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AckIn"
       }
      }
     },
     "required": true,
     "description": "Optional note."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Ack Alert Api V1 Alerts  Alert Id  Ack Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Acknowledge an alert",
    "tags": [
     "alerts"
    ],
    "description": "Records who acknowledged the alert, when, and the note; the alert stays open until its condition clears. Returns the alert. Permission `alerts:manage` on its cluster. Audited as `alert.ack`."
   }
  },
  "/api/v1/audit": {
   "get": {
    "operationId": "list_audit_api_v1_audit_get",
    "parameters": [
     {
      "in": "query",
      "name": "actor",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 200,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Actor"
      },
      "description": "Name or identifier of the actor, exact match."
     },
     {
      "in": "query",
      "name": "action",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 200,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Action"
      },
      "description": "Action, exact match (`auth.login`) or a family ending with `.*` (`service.*`)."
     },
     {
      "in": "query",
      "name": "target_type",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 100,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Target Type"
      },
      "description": "Type of the target, for example `user`, `service`, `cluster` or `operation`."
     },
     {
      "in": "query",
      "name": "cluster_id",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 64,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Cluster Id"
      },
      "description": "Only the events of this cluster."
     },
     {
      "in": "query",
      "name": "outcome",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "enum": [
          "success",
          "failure",
          "denied"
         ],
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Outcome"
      },
      "description": "Outcome: `success`, `failure` or `denied`."
     },
     {
      "in": "query",
      "name": "from",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "format": "date-time",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "From"
      },
      "description": "Events at or after this date and time (ISO 8601)."
     },
     {
      "in": "query",
      "name": "to",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "format": "date-time",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "To"
      },
      "description": "Events before this date and time (ISO 8601), excluded."
     },
     {
      "in": "query",
      "name": "limit",
      "required": false,
      "schema": {
       "default": 50,
       "maximum": 500,
       "minimum": 1,
       "title": "Limit",
       "type": "integer"
      },
      "description": "Maximum number of events in the page, from 1 to 500. Default 50."
     },
     {
      "in": "query",
      "name": "cursor",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 30,
         "pattern": "^[0-9]+$",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Cursor"
      },
      "description": "The `next_cursor` of the previous page (a sequence number). Omit it for the first page."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Audit Api V1 Audit Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Search the audit trail",
    "tags": [
     "audit"
    ],
    "description": "Events matching every filter given, newest first: `seq`, `id`, `ts`, `actor_type`, `actor_id`, `actor_name`, `action`, `target_type`, `target_id`, `cluster_id`, `outcome`, `ip`, `details`, `prev_hash`, `hash`. Paginated with `limit` and `cursor`. Permission `audit:read`."
   }
  },
  "/api/v1/audit/export": {
   "get": {
    "operationId": "export_api_v1_audit_export_get",
    "parameters": [
     {
      "in": "query",
      "name": "format",
      "required": false,
      "schema": {
       "default": "ndjson",
       "maxLength": 10,
       "title": "Format",
       "type": "string"
      },
      "description": "File format: `ndjson` (default) or `csv`."
     },
     {
      "in": "query",
      "name": "from",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "format": "date-time",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "From"
      },
      "description": "Events at or after this date and time (ISO 8601). Omit it to start at the first event."
     },
     {
      "in": "query",
      "name": "to",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "format": "date-time",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "To"
      },
      "description": "Events before this date and time (ISO 8601), excluded. Omit it to export up to now."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {}
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Export the audit trail",
    "tags": [
     "audit"
    ],
    "description": "Streams every event of the period in sequence order as a file download: `audit.ndjson` (one JSON object per line) or `audit.csv` (cells a spreadsheet would read as a formula are prefixed with a quote). Permission `audit:read`; `422 export_format_invalid` for another format. Audited as `audit.export`."
   }
  },
  "/api/v1/audit/verify": {
   "get": {
    "operationId": "verify_api_v1_audit_verify_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Verify Api V1 Audit Verify Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Verify the hash chain of the audit trail",
    "tags": [
     "audit"
    ],
    "description": "Recomputes the hash of every event and checks the link to the previous one. Returns `valid`, the number of events `checked` and `first_broken_seq` (null when the chain is intact). Permission `audit:read`. Audited as `audit.verify` (outcome `failure` when the chain is broken)."
   }
  },
  "/api/v1/auth-config/ldap": {
   "get": {
    "operationId": "get_ldap_api_v1_auth_config_ldap_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Ldap Api V1 Auth Config Ldap Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the LDAP configuration",
    "tags": [
     "auth-config"
    ],
    "description": "Returns the LDAP settings with their defaults, the bind password as `{\"secret\": true, \"set\": ...}` and the role mappings. Permission `auth:manage`."
   },
   "put": {
    "operationId": "put_ldap_api_v1_auth_config_ldap_put",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LdapBody"
       }
      }
     },
     "required": true,
     "description": "Complete LDAP settings."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Put Ldap Api V1 Auth Config Ldap Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Save the LDAP configuration",
    "tags": [
     "auth-config"
    ],
    "description": "Replaces the LDAP settings and role mappings and returns them. Every URL must be protected by TLS (`ldaps://`, or `ldap://` with `start_tls`), at least one URL is needed when enabled, filters must be balanced in parentheses. Permission `auth:manage`. Errors: `422 ldap_config_invalid` (with `details.problems`), `422 role_invalid`. Audited as `auth_config.ldap`."
   }
  },
  "/api/v1/auth-config/ldap/test": {
   "post": {
    "operationId": "test_ldap_api_v1_auth_config_ldap_test_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LdapTestBody"
       }
      }
     },
     "required": true,
     "description": "Optional test account."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Test Ldap Api V1 Auth Config Ldap Test Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Test the LDAP configuration",
    "tags": [
     "auth-config"
    ],
    "description": "Binds with the stored settings and, when a test account is given, searches the user, checks its password and reads its groups. Returns `ok`, `bind`, `user_found`, `groups` and `error_code`. Nothing is changed. Permission `auth:manage`; `404 ldap_not_configured`. Audited as `auth_config.ldap_test`."
   }
  },
  "/api/v1/auth-config/oidc": {
   "get": {
    "operationId": "list_oidc_api_v1_auth_config_oidc_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Oidc Api V1 Auth Config Oidc Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the OIDC providers",
    "tags": [
     "auth-config"
    ],
    "description": "Every OIDC provider, enabled or not, with its settings and mappings; client secrets are never returned. Permission `auth:manage`."
   },
   "post": {
    "operationId": "create_oidc_api_v1_auth_config_oidc_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OidcBody"
       }
      }
     },
     "required": true,
     "description": "Settings of the provider."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Oidc Api V1 Auth Config Oidc Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Add an OIDC provider",
    "tags": [
     "auth-config"
    ],
    "description": "Creates a provider and returns it (`201`). The scopes must include `openid`. Permission `auth:manage`. Errors: `409 provider_name_taken`, `422 oidc_config_invalid`, `422 role_invalid`. Audited."
   }
  },
  "/api/v1/auth-config/oidc/{provider_id}": {
   "delete": {
    "operationId": "delete_oidc_api_v1_auth_config_oidc__provider_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "provider_id",
      "required": true,
      "schema": {
       "title": "Provider Id",
       "type": "string"
      },
      "description": "Identifier of the OIDC provider."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete an OIDC provider",
    "tags": [
     "auth-config"
    ],
    "description": "Removes the provider; its users can no longer sign in through it. Answers `204`. Permission `auth:manage`; `404 oidc_provider_not_found`. Audited as `auth_config.oidc_delete`."
   },
   "get": {
    "operationId": "get_oidc_api_v1_auth_config_oidc__provider_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "provider_id",
      "required": true,
      "schema": {
       "title": "Provider Id",
       "type": "string"
      },
      "description": "Identifier of the OIDC provider."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Oidc Api V1 Auth Config Oidc  Provider Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get an OIDC provider",
    "tags": [
     "auth-config"
    ],
    "description": "Returns one provider with its settings and mappings. Permission `auth:manage`; `404 oidc_provider_not_found`."
   },
   "put": {
    "operationId": "put_oidc_api_v1_auth_config_oidc__provider_id__put",
    "parameters": [
     {
      "in": "path",
      "name": "provider_id",
      "required": true,
      "schema": {
       "title": "Provider Id",
       "type": "string"
      },
      "description": "Identifier of the OIDC provider."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OidcBody"
       }
      }
     },
     "required": true,
     "description": "Complete settings of the provider."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Put Oidc Api V1 Auth Config Oidc  Provider Id  Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update an OIDC provider",
    "tags": [
     "auth-config"
    ],
    "description": "Replaces the settings and mappings of the provider and returns it; the client secret is kept unless a new one is sent. Permission `auth:manage`. Errors: `404 oidc_provider_not_found`, `409 provider_name_taken`, `422 oidc_config_invalid`. Audited."
   }
  },
  "/api/v1/auth-config/oidc/{provider_id}/test": {
   "post": {
    "operationId": "test_oidc_api_v1_auth_config_oidc__provider_id__test_post",
    "parameters": [
     {
      "in": "path",
      "name": "provider_id",
      "required": true,
      "schema": {
       "title": "Provider Id",
       "type": "string"
      },
      "description": "Identifier of the OIDC provider."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Test Oidc Api V1 Auth Config Oidc  Provider Id  Test Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Test an OIDC provider",
    "tags": [
     "auth-config"
    ],
    "description": "Reads the discovery document of the issuer and its signing keys. Returns `ok`, `issuer`, `jwks_keys` (number of keys) and `error_code`. Permission `auth:manage`; `404 oidc_provider_not_found`. Audited as `auth_config.oidc_test`."
   }
  },
  "/api/v1/auth-config/policy": {
   "get": {
    "operationId": "get_policy_api_v1_auth_config_policy_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Policy Api V1 Auth Config Policy Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the security policy",
    "tags": [
     "auth-config"
    ],
    "description": "Returns the current policy, defaults included: password minimum length 12, history 5, no maximum age, lockout after 5 failures for 15 minutes, sessions of 30 idle minutes and 12 hours at most, MFA required for `admin` and `security_admin`. Permission `auth:manage`."
   },
   "put": {
    "operationId": "put_policy_api_v1_auth_config_policy_put",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PolicyBody"
       }
      }
     },
     "required": true,
     "description": "Every field of the policy."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Put Policy Api V1 Auth Config Policy Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Save the security policy",
    "tags": [
     "auth-config"
    ],
    "description": "Replaces the whole policy and returns it. It applies to the next password change, sign in and session check. Permission `auth:manage`; `422 role_invalid` for an unknown role in `mfa_required_roles`. Audited as `auth_config.policy`."
   }
  },
  "/api/v1/auth/login": {
   "post": {
    "operationId": "login_api_v1_auth_login_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LoginBody"
       }
      }
     },
     "required": true,
     "description": "Username, password and provider (`local` or `ldap`)."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Login Api V1 Auth Login Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Sign in with a username and a password",
    "tags": [
     "auth"
    ],
    "description": "Checks a local or LDAP account. Answers one of:\n\n- the session (`user`, `permissions`, `csrf_token`, `expires_at`) with the `nm_session` cookie set;\n- `{\"mfa_required\": true, \"mfa_token\": ..., \"enrollment_required\": ...}` when the second factor is needed (the\n  token is valid 5 minutes and 5 attempts);\n- an error: `401 invalid_credentials`, `423 account_locked` (`details.locked_until`), `403 account_disabled`,\n  `403 password_expired` (`details.password_change_token`, `details.reason` `change_required` or `expired`),\n  `400 ldap_disabled`, `503 ldap_unavailable`, `429 too_many_attempts`.\n\nAn LDAP sign in creates or updates the user and replaces its LDAP role bindings by the mapped groups. Audited\nas `auth.login`."
   }
  },
  "/api/v1/auth/logout": {
   "post": {
    "operationId": "logout_api_v1_auth_logout_post",
    "responses": {
     "204": {
      "description": "Successful Response"
     }
    },
    "summary": "Sign out",
    "tags": [
     "auth"
    ],
    "description": "Revokes the current session and clears the session cookie. Answers `204`, also when the session already expired. Audited as `auth.logout`."
   }
  },
  "/api/v1/auth/mfa": {
   "delete": {
    "description": "Turns off the TOTP second factor of the signed in user and deletes its recovery codes. A local account confirms\nwith its password, an LDAP or OIDC account with a current TOTP code. Browser session only. Answers `204`.\nErrors: `403 mfa_required_by_policy` (a role of the user requires MFA), `409 mfa_not_enabled`,\n`401 invalid_credentials`, `401 invalid_mfa_code`, `429 too_many_attempts`. Audited as `auth.mfa_disabled`.",
    "operationId": "mfa_disable_api_v1_auth_mfa_delete",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MfaDisableBody"
       }
      }
     },
     "required": true,
     "description": "Password (local account) or current TOTP code (LDAP or OIDC account)."
    },
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Turn off my second factor",
    "tags": [
     "auth"
    ]
   }
  },
  "/api/v1/auth/mfa/confirm": {
   "post": {
    "description": "Second step of the self service enrollment: checks a code of the secret given by `POST /auth/mfa/setup`, turns\nMFA on and returns ten single use `recovery_codes`, shown only once. Browser session only. Errors:\n`409 mfa_disabled`, `409 mfa_already_enabled`, `409 mfa_enrollment_not_started`, `401 invalid_mfa_code`.\nAudited as `auth.mfa_enrolled`.",
    "operationId": "mfa_confirm_api_v1_auth_mfa_confirm_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MfaConfirmBody"
       }
      }
     },
     "required": true,
     "description": "Current code of the authenticator application."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Mfa Confirm Api V1 Auth Mfa Confirm Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Confirm my second factor",
    "tags": [
     "auth"
    ]
   }
  },
  "/api/v1/auth/mfa/enroll/confirm": {
   "post": {
    "operationId": "mfa_enroll_confirm_api_v1_auth_mfa_enroll_confirm_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/EnrollConfirmBody"
       }
      }
     },
     "required": true,
     "description": "Login challenge token and the first code of the new secret."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Mfa Enroll Confirm Api V1 Auth Mfa Enroll Confirm Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Confirm the forced enrollment at sign in",
    "tags": [
     "auth"
    ],
    "description": "Second step of the enrollment required at sign in: checks the code of the pending secret, turns MFA on, then\nopens the session like a login and adds the `recovery_codes` (shown once) to the answer. Errors:\n`401 mfa_token_invalid`, `409 mfa_already_enabled`, `409 mfa_enrollment_not_started`, `401 invalid_mfa_code`,\n`403 password_expired`. Audited as `auth.mfa_enrolled`."
   }
  },
  "/api/v1/auth/mfa/enroll/start": {
   "post": {
    "operationId": "mfa_enroll_start_api_v1_auth_mfa_enroll_start_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/EnrollStartBody"
       }
      }
     },
     "required": true,
     "description": "Login challenge token."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Mfa Enroll Start Api V1 Auth Mfa Enroll Start Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Start the forced enrollment at sign in",
    "tags": [
     "auth"
    ],
    "description": "First step of the enrollment required by the security policy, with the `mfa_token` of the login. Generates a\nTOTP secret and returns `secret` and `otpauth_uri` (to show as a QR code). Errors: `401 mfa_token_invalid`,\n`409 mfa_already_enabled`. Audited as `auth.mfa_enroll_start`."
   }
  },
  "/api/v1/auth/mfa/setup": {
   "post": {
    "description": "Self service, from a browser session: generates a pending TOTP secret and returns `secret` and `otpauth_uri`.\nFinish with `POST /auth/mfa/confirm`. Errors: `409 mfa_disabled` (TOTP turned off on this Manager),\n`409 mfa_already_enabled`, `403 session_required`. Audited as `auth.mfa_setup`.",
    "operationId": "mfa_setup_api_v1_auth_mfa_setup_post",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Mfa Setup Api V1 Auth Mfa Setup Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Start enrolling my second factor",
    "tags": [
     "auth"
    ]
   }
  },
  "/api/v1/auth/mfa/verify": {
   "post": {
    "operationId": "mfa_verify_api_v1_auth_mfa_verify_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MfaVerifyBody"
       }
      }
     },
     "required": true,
     "description": "Login challenge token with a TOTP code or a recovery code."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Mfa Verify Api V1 Auth Mfa Verify Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Verify the second factor of a sign in",
    "tags": [
     "auth"
    ],
    "description": "Second step of a login: send the `mfa_token` with a TOTP `code` or a `recovery_code` (each recovery code works\nonce; a TOTP code cannot be replayed). On success the session opens like a login. A wrong code counts as a\nfailed login; after 5 wrong codes the token is dropped. Errors: `401 mfa_token_invalid`,\n`401 invalid_mfa_code`, `423 account_locked`, `403 password_expired`, `429 too_many_attempts`. Audited as\n`auth.mfa`."
   }
  },
  "/api/v1/auth/oidc/{provider_id}/callback": {
   "get": {
    "operationId": "oidc_callback_api_v1_auth_oidc__provider_id__callback_get",
    "parameters": [
     {
      "in": "path",
      "name": "provider_id",
      "required": true,
      "schema": {
       "title": "Provider Id",
       "type": "string"
      },
      "description": "Identifier of the OIDC provider."
     },
     {
      "in": "query",
      "name": "code",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Code"
      },
      "description": "Authorization code returned by the provider."
     },
     {
      "in": "query",
      "name": "state",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "State"
      },
      "description": "State value created by the start step, checked against the `nm_oidc_state` cookie."
     },
     {
      "in": "query",
      "name": "error",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Error"
      },
      "description": "Error returned by the provider when the user refused or the request failed."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {}
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Finish an OIDC sign in (redirect target)",
    "tags": [
     "auth"
    ],
    "description": "Redirect target registered at the OIDC provider; the browser comes back here, never a script. The Manager checks\nthe `state` against the cookie set by the start step, exchanges the code (PKCE), verifies the ID token (issuer,\naudience, nonce, signature), creates or updates the user, maps its groups to roles, then answers `302`: to the\npage asked at the start with the session cookie set, to `/login?mfa=1` when the second factor is required, or to\n`/login?error=<code>` on a failure (`oidc_state_invalid`, `oidc_denied`, `oidc_user_conflict`...). Audited as\n`auth.login` and `user.oidc_sync`."
   }
  },
  "/api/v1/auth/oidc/{provider_id}/start": {
   "get": {
    "operationId": "oidc_start_api_v1_auth_oidc__provider_id__start_get",
    "parameters": [
     {
      "in": "path",
      "name": "provider_id",
      "required": true,
      "schema": {
       "title": "Provider Id",
       "type": "string"
      },
      "description": "Identifier of the OIDC provider, from `GET /auth/providers`."
     },
     {
      "in": "query",
      "name": "redirect",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 512,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Redirect"
      },
      "description": "Path of the console to open after the sign in, for example `/clusters`. At most 512 characters; default `/`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {}
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Start an OIDC sign in",
    "tags": [
     "auth"
    ],
    "description": "Open this URL in the browser: it discovers the provider, stores a state, a nonce and a PKCE verifier valid for\n10 minutes, sets the `nm_oidc_state` cookie and answers `302` to the authorization page of the provider. A\ndisabled or unreachable provider redirects to `/login?error=<code>`. A `redirect` that leaves the console is\nreplaced by `/` and audited as `auth.oidc_redirect_refused`."
   }
  },
  "/api/v1/auth/password/change": {
   "post": {
    "operationId": "password_change_api_v1_auth_password_change_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PasswordChangeBody"
       }
      }
     },
     "required": true,
     "description": "New password with the current password or the password change token."
    },
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Change a password",
    "tags": [
     "auth"
    ],
    "description": "Two uses:\n\n1. signed in with a local account: send `current_password` and `new_password`;\n2. at sign in, after `403 password_expired`: send the `password_change_token` of the error and `new_password`\n   (no session needed).\n\nThe new password must follow the security policy (length, character classes, not the username, not one of the\nlast passwords): else `422 password_policy` with the broken `details.rules`. On success the other sessions of\nthe user are revoked and the API answers `204`. Errors: `401 password_change_token_invalid`,\n`401 invalid_credentials`, `409 not_local_user`, `429 too_many_attempts`. Audited as `auth.password_change`."
   }
  },
  "/api/v1/auth/providers": {
   "get": {
    "operationId": "providers_api_v1_auth_providers_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Providers Api V1 Auth Providers Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the sign in methods",
    "tags": [
     "auth"
    ],
    "description": "Public endpoint used by the login page. Returns `local` (always true), `ldap` (`enabled`, `name`), `oidc` (the\nenabled providers, `id` and `name`), `setup_required` (true while no user exists: call `POST /auth/setup`) and\n`mfa` (whether the TOTP second factor is turned on for this Manager)."
   }
  },
  "/api/v1/auth/session": {
   "get": {
    "operationId": "session_api_v1_auth_session_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Session Api V1 Auth Session Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Read the current session",
    "tags": [
     "auth"
    ],
    "description": "Returns the authenticated user (`user`), its effective permissions (`permissions.global` and\n`permissions.clusters` by cluster identifier), the `csrf_token` of the session (null for an API token) and\n`expires_at` (of the session or of the token). Any authenticated caller; `401` otherwise."
   }
  },
  "/api/v1/auth/setup": {
   "post": {
    "operationId": "setup_api_v1_auth_setup_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SetupBody"
       }
      }
     },
     "required": true,
     "description": "Username, password and display name of the first administrator."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Setup Api V1 Auth Setup Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create the first administrator",
    "tags": [
     "auth"
    ],
    "description": "First run only, while no user exists: creates a local account with the global `admin` role and signs it in\n(same answers as a login). Errors: `409 setup_done` once a user exists, `422 password_policy`,\n`429 too_many_attempts`. Audited as `auth.setup`."
   }
  },
  "/api/v1/backup-jobs": {
   "get": {
    "operationId": "list_jobs_api_v1_backup_jobs_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Jobs Api V1 Backup Jobs Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the backup jobs",
    "tags": [
     "backup"
    ],
    "description": "The last 200 backup jobs, newest first, with their plan name, status and error. Permission `backup:read`."
   }
  },
  "/api/v1/backup-plans": {
   "get": {
    "operationId": "list_plans_api_v1_backup_plans_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Plans Api V1 Backup Plans Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the backup plans",
    "tags": [
     "backup"
    ],
    "description": "Every backup plan, and `alerts`: the plans whose last successful backup is older than the interval plus the window, or whose last job failed. Permission `backup:read`."
   },
   "post": {
    "operationId": "create_plan_api_v1_backup_plans_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PlanIn"
       }
      }
     },
     "required": true,
     "description": "Target, scope, schedule, encryption and retention of the plan."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Plan Api V1 Backup Plans Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create a backup plan",
    "tags": [
     "backup"
    ],
    "description": "Creates a backup plan on a target and returns it (`201`). With `immutability_required` the target must have verified object lock and retention capabilities. Permission `backup:manage`. Errors: `404 backup_target_not_found`, `409 backup_worm_unsupported`. Audited as `backup.plan.create`."
   }
  },
  "/api/v1/backup-plans/{plan_id}/backups": {
   "post": {
    "operationId": "record_backup_api_v1_backup_plans__plan_id__backups_post",
    "parameters": [
     {
      "in": "path",
      "name": "plan_id",
      "required": true,
      "schema": {
       "title": "Plan Id",
       "type": "string"
      },
      "description": "Identifier of the backup plan."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ArtifactIn"
       }
      }
     },
     "required": true,
     "description": "Location, kind and versions of the artefact."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Record Backup Api V1 Backup Plans  Plan Id  Backups Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Record a backup",
    "tags": [
     "backup"
    ],
    "description": "Records one job and its artefact: the Manager hashes the file at `location`, stores its digest, size and versions, and sets `expires_at` from the retention of the plan. When the file cannot be read the job is recorded as `failed`. Returns the job with its `artifact` (`201`). Permission `backup:manage`; `404 backup_policy_not_found`. Audited as `backup.job`."
   }
  },
  "/api/v1/backup-targets": {
   "post": {
    "operationId": "create_target_api_v1_backup_targets_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__backup_recovery__TargetIn"
       }
      }
     },
     "required": true,
     "description": "Provider, location and capabilities of the target."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Target Api V1 Backup Targets Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Declare a backup target",
    "tags": [
     "backup"
    ],
    "description": "Creates a target and returns it (`201`). Permission `backup:manage`; `422 backup_provider_unsupported`. Audited as `backup.target.create`."
   }
  },
  "/api/v1/backups": {
   "get": {
    "operationId": "list_backups_api_v1_backups_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Backups Api V1 Backups Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the backups",
    "tags": [
     "backup"
    ],
    "description": "The last 200 backup artefacts, newest first: location, SHA-256, size, versions, expiry, plan and the outcome of their last verification. Permission `backup:read`."
   }
  },
  "/api/v1/backups/consistency": {
   "post": {
    "description": "Compares the database rows, the stored objects and the artefact registry of a filesystem target (its `bucket` is the root directory). With `reconcile`, rows whose object is gone are marked `missing` and orphan objects are moved into a quarantine directory, never deleted. Permission `backup:manage`. Errors: `404 backup_target_not_found`, `422 backup_provider_unsupported` (not `filesystem`).",
    "operationId": "backup_consistency_api_v1_backups_consistency_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ConsistencyIn"
       }
      }
     },
     "required": true,
     "description": "Target, registry digests and reconcile flag."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Backup Consistency Api V1 Backups Consistency Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Check the consistency of a backup target",
    "tags": [
     "backup"
    ]
   }
  },
  "/api/v1/backups/retention/enforce": {
   "post": {
    "operationId": "enforce_retention_api_v1_backups_retention_enforce_post",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Enforce Retention Api V1 Backups Retention Enforce Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Apply the retention now",
    "tags": [
     "backup"
    ],
    "description": "Removes the artefacts past their `expires_at` and marks them `expired`. Returns `expired`. Permission `backup:manage`. Audited as `backup.expire`."
   }
  },
  "/api/v1/backups/{backup_id}": {
   "delete": {
    "operationId": "delete_backup_api_v1_backups__backup_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "backup_id",
      "required": true,
      "schema": {
       "title": "Backup Id",
       "type": "string"
      },
      "description": "Identifier of the backup artefact."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Delete Backup Api V1 Backups  Backup Id  Delete",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete a backup",
    "tags": [
     "backup"
    ],
    "description": "Deletes a backup artefact whose retention is over. Permission `backup:manage`. Errors: `409 backup_retention_active` (before `expires_at`), `404 backup_artifact_not_found`. Audited as `backup.delete`."
   }
  },
  "/api/v1/backups/{backup_id}/restore-tests": {
   "post": {
    "operationId": "run_restore_test_api_v1_backups__backup_id__restore_tests_post",
    "parameters": [
     {
      "in": "path",
      "name": "backup_id",
      "required": true,
      "schema": {
       "title": "Backup Id",
       "type": "string"
      },
      "description": "Identifier of the backup artefact."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RestoreTestIn"
       }
      }
     },
     "required": true,
     "description": "Whether to inject a corruption (to prove the test catches it)."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Run Restore Test Api V1 Backups  Backup Id  Restore Tests Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run a restore test",
    "tags": [
     "backup"
    ],
    "description": "Copies the artefact into an isolated directory, optionally injects a corruption, verifies the digest and the decryption and signs the report (Ed25519). A failure raises an audited alarm. Returns the test (`201`). Permission `backup:manage`. Audited as `backup.restore_test`."
   }
  },
  "/api/v1/backups/{backup_id}/verifications": {
   "get": {
    "operationId": "list_verifications_api_v1_backups__backup_id__verifications_get",
    "parameters": [
     {
      "in": "path",
      "name": "backup_id",
      "required": true,
      "schema": {
       "title": "Backup Id",
       "type": "string"
      },
      "description": "Identifier of the backup artefact."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Verifications Api V1 Backups  Backup Id  Verifications Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the verifications of a backup",
    "tags": [
     "backup"
    ],
    "description": "Every verification of the artefact, newest first, with its `outcome` (`passed` or `failed`) and details (expected and observed digest, size, reason). Permission `backup:read`."
   }
  },
  "/api/v1/backups/{backup_id}/verify": {
   "post": {
    "operationId": "verify_backup_api_v1_backups__backup_id__verify_post",
    "parameters": [
     {
      "in": "path",
      "name": "backup_id",
      "required": true,
      "schema": {
       "title": "Backup Id",
       "type": "string"
      },
      "description": "Identifier of the backup artefact."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Verify Backup Api V1 Backups  Backup Id  Verify Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Verify a backup",
    "tags": [
     "backup"
    ],
    "description": "Hashes the file again, compares digest and size with the recorded ones and, when they match, decrypts it with its key. Returns the verification with its `outcome` (`passed` or `failed`). Permission `backup:manage`; `404 backup_artifact_not_found`. Audited as `backup.verify`."
   }
  },
  "/api/v1/breakglass/{request_id}/approve": {
   "post": {
    "operationId": "breakglass_approve_api_v1_breakglass__request_id__approve_post",
    "parameters": [
     {
      "in": "path",
      "name": "request_id",
      "required": true,
      "schema": {
       "title": "Request Id",
       "type": "string"
      },
      "description": "Identifier of the break glass request."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Breakglass Approve Api V1 Breakglass  Request Id  Approve Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Approve a break glass request",
    "tags": [
     "node-security"
    ],
    "description": "Adds an approval. Two distinct approvers, both different from the requester, are needed; the second approval signs an OpenSSH user certificate valid for the TTL. Permission `hosts:manage`. Errors: `403 breakglass_self_approval`, `409 breakglass_not_pending`, `409 breakglass_already_approved`, `404 breakglass_not_found`. Audited as `host.breakglass.approve`."
   }
  },
  "/api/v1/breakglass/{request_id}/evidence": {
   "post": {
    "operationId": "breakglass_evidence_api_v1_breakglass__request_id__evidence_post",
    "parameters": [
     {
      "in": "path",
      "name": "request_id",
      "required": true,
      "schema": {
       "title": "Request Id",
       "type": "string"
      },
      "description": "Identifier of the break glass request."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/EvidenceIn"
       }
      }
     },
     "required": true,
     "description": "Kind, digest and summary of the evidence."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Breakglass Evidence Api V1 Breakglass  Request Id  Evidence Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Add evidence to a break glass session",
    "tags": [
     "node-security"
    ],
    "description": "Appends a redacted evidence record (session start, command digest, session end or recording) to the request. Permission `hosts:manage`; `404 breakglass_not_found`."
   }
  },
  "/api/v1/breakglass/{request_id}/revoke": {
   "post": {
    "operationId": "breakglass_revoke_api_v1_breakglass__request_id__revoke_post",
    "parameters": [
     {
      "in": "path",
      "name": "request_id",
      "required": true,
      "schema": {
       "title": "Request Id",
       "type": "string"
      },
      "description": "Identifier of the break glass request."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Breakglass Revoke Api V1 Breakglass  Request Id  Revoke Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Revoke a break glass access early",
    "tags": [
     "node-security"
    ],
    "description": "Ends the access before its TTL: the certificate is added to the key revocation list the hosts load. Permission `hosts:manage`. Errors: `404 breakglass_not_found`, `409 breakglass_not_active`."
   }
  },
  "/api/v1/catalog/high-availability": {
   "get": {
    "description": "High availability matrix of every catalog service, sorted by category then name: its modes (topologies) with the cardinality of each component, and its high availability block with the liveness and readiness checks. Returns `items` and `count`. Any signed in user.",
    "operationId": "high_availability_api_v1_catalog_high_availability_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response High Availability Api V1 Catalog High Availability Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the high availability matrix of the catalog",
    "tags": [
     "stack"
    ]
   }
  },
  "/api/v1/clusters": {
   "get": {
    "operationId": "list_clusters_api_v1_clusters_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Clusters Api V1 Clusters Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the clusters",
    "tags": [
     "clusters"
    ],
    "description": "Clusters the caller may read (`cluster:read` globally or on the cluster), sorted by name: `id`, `name`, `mode`, `description`, `stack_version`, `profile`, `kind` (`hosts` or `kubernetes`), `created_at`, `updated_at`."
   },
   "post": {
    "operationId": "create_cluster_api_v1_clusters_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ClusterIn"
       }
      }
     },
     "required": true,
     "description": "Name, mode, description and profile of the cluster."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Cluster Api V1 Clusters Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create a cluster",
    "tags": [
     "clusters"
    ],
    "description": "Creates an empty cluster on the current catalog version and returns it (`201`). Without a profile, `production` and `preprod` clusters get `standard`, the other modes `development`. Permission `clusters:create`; `409 cluster_name_taken` (names are case insensitive). Audited as `cluster.create`."
   }
  },
  "/api/v1/clusters/{cluster_id}": {
   "delete": {
    "operationId": "delete_cluster_api_v1_clusters__cluster_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete an empty cluster",
    "tags": [
     "clusters"
    ],
    "description": "Deletes a cluster that has no service and no host other than decommissioned ones. Answers `204`. Permission `cluster:manage`. Errors: `404 cluster_not_found`, `409 cluster_not_empty`. Audited as `cluster.delete`."
   },
   "get": {
    "operationId": "get_cluster_api_v1_clusters__cluster_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Cluster Api V1 Clusters  Cluster Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a cluster",
    "tags": [
     "clusters"
    ],
    "description": "Returns the cluster. Permission `cluster:read`; `404 cluster_not_found`."
   },
   "patch": {
    "operationId": "patch_cluster_api_v1_clusters__cluster_id__patch",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ClusterPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the cluster to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Patch Cluster Api V1 Clusters  Cluster Id  Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Rename a cluster or change its profile",
    "tags": [
     "clusters"
    ],
    "description": "Changes the name, the description or the profile; a field left out is kept. Returns the cluster. Permission `cluster:manage`. Errors: `404 cluster_not_found`, `409 cluster_name_taken`. Audited as `cluster.update`."
   }
  },
  "/api/v1/clusters/{cluster_id}/acceptance-reports": {
   "get": {
    "operationId": "list_reports_api_v1_clusters__cluster_id__acceptance_reports_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response List Reports Api V1 Clusters  Cluster Id  Acceptance Reports Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the acceptance reports of a cluster",
    "tags": [
     "lifecycle"
    ],
    "description": "The last 100 acceptance runs of the cluster, newest first, with their status, verdict and operation. Permission `cluster:read`."
   },
   "post": {
    "operationId": "create_report_api_v1_clusters__cluster_id__acceptance_reports_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Report Api V1 Clusters  Cluster Id  Acceptance Reports Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run an acceptance",
    "tags": [
     "lifecycle"
    ],
    "description": "Starts the `acceptance.run` operation: cluster preflight, liveness of every running instance, readiness and smoke test of every managed service (each stage tolerates its failures so that every check runs), then the signed report. Returns `operation_id` and `report_id`. Permission `services:install`. Audited as `acceptance.run`."
   }
  },
  "/api/v1/clusters/{cluster_id}/acceptance-reports/{report_id}": {
   "get": {
    "operationId": "get_report_api_v1_clusters__cluster_id__acceptance_reports__report_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "report_id",
      "required": true,
      "schema": {
       "title": "Report Id",
       "type": "string"
      },
      "description": "Identifier of the acceptance report."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Report Api V1 Clusters  Cluster Id  Acceptance Reports  Report Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a signed acceptance report",
    "tags": [
     "lifecycle"
    ],
    "description": "Returns the signed document: one item per check with `PASS`, `FAIL` or `BLOCKED` and its evidence, the verdict (`FAIL` when one item failed, `BLOCKED` when none failed and one is blocked, else `PASS`) and the signature. Permission `cluster:read`; `404 acceptance_not_found` until the run succeeded."
   }
  },
  "/api/v1/clusters/{cluster_id}/acceptance-reports/{report_id}/html": {
   "get": {
    "operationId": "report_html_api_v1_clusters__cluster_id__acceptance_reports__report_id__html_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "report_id",
      "required": true,
      "schema": {
       "title": "Report Id",
       "type": "string"
      },
      "description": "Identifier of the acceptance report."
     },
     {
      "in": "query",
      "name": "lang",
      "required": false,
      "schema": {
       "default": "en",
       "enum": [
        "en",
        "fr"
       ],
       "title": "Lang",
       "type": "string"
      },
      "description": "Language of the page: `en` (default) or `fr`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {}
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get an acceptance report as HTML",
    "tags": [
     "lifecycle"
    ],
    "description": "Renders the report as a self contained HTML page in the language asked, for printing or archiving. Permission `cluster:read`; `404 acceptance_not_found`."
   }
  },
  "/api/v1/clusters/{cluster_id}/actions": {
   "post": {
    "operationId": "cluster_action_api_v1_clusters__cluster_id__actions_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ClusterActionBody"
       }
      }
     },
     "required": true,
     "description": "Action, scope, batching and dry run."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Cluster Action Api V1 Clusters  Cluster Id  Actions Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run an action on every service of a cluster",
    "tags": [
     "services"
    ],
    "description": "Starts one operation that runs the action on every managed service in scope (every service by default, or those of `services`, on every host or on `hosts`), in dependency order: a provider starts before its consumers and stops after them. `restart` stops every service in reverse order, then starts every service in order with the health checks; `rolling_restart` restarts each service by batches of `batch_size` hosts; `restart_stale` writes again the files and units of the instances whose configuration changed, then restarts them by batches; `service_check` runs the check of every service. Connected services, services being installed or uninstalled, an administrative state that forbids the action and instances in maintenance, being removed or on a decommissioned host are left out and listed in `skipped` with the reason. Returns `services` in dependency order, `skipped`, `steps` and `operation_id`; with `dry_run` nothing is created and `operation_id` is null. Permission `services:operate`. Errors: `409 bulk_nothing_to_do`, `404 cluster_service_not_found`, `409 profile_blocked`, `409 approval_required` (under `banking-secure`, stop and restarts need an approval for the service `*`). Audited as `cluster.<action>`."
   }
  },
  "/api/v1/clusters/{cluster_id}/alerts": {
   "get": {
    "description": "Alerts of the cluster, last changed first (at most 500): `definition`, `label`, `fingerprint`, host, service, component, `state`, `text`, `value`, first and last seen, acknowledgement and resolution. Open alerts only unless `include_resolved`. Permission `alerts:read`.",
    "operationId": "list_alerts_api_v1_clusters__cluster_id__alerts_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "state",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "State"
      },
      "description": "Only the alerts in this state: `warning`, `critical`, `unknown` or `ok`."
     },
     {
      "in": "query",
      "name": "severity",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Severity"
      },
      "description": "Only the alerts of this severity (`warning` or `critical`); compared with the state of the alert."
     },
     {
      "in": "query",
      "name": "include_resolved",
      "required": false,
      "schema": {
       "default": false,
       "title": "Include Resolved",
       "type": "boolean"
      },
      "description": "Also return the resolved alerts. Default false."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Alerts Api V1 Clusters  Cluster Id  Alerts Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the alerts of a cluster",
    "tags": [
     "alerts"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/approvals": {
   "get": {
    "operationId": "list_approvals_api_v1_clusters__cluster_id__approvals_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response List Approvals Api V1 Clusters  Cluster Id  Approvals Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the approvals of a cluster",
    "tags": [
     "lifecycle"
    ],
    "description": "The last 200 approvals, newest first: `action`, `service`, `reason`, `status` (`pending`, `approved`, `rejected`, `expired` or `used`), requester, decider, the operation that used it and the times. Approvals past their expiry are marked `expired` first. Permission `cluster:read`."
   },
   "post": {
    "operationId": "request_approval_api_v1_clusters__cluster_id__approvals_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ApprovalBody"
       }
      }
     },
     "required": true,
     "description": "Action, service and reason."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Request Approval Api V1 Clusters  Cluster Id  Approvals Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Request an approval",
    "tags": [
     "lifecycle"
    ],
    "description": "Records a pending request for a disruptive action on a service; another user decides it. Returns the approval (`201`). Permission `services:operate`. Audited as `approval.request`."
   }
  },
  "/api/v1/clusters/{cluster_id}/approvals/{approval_id}/decision": {
   "post": {
    "operationId": "decide_approval_api_v1_clusters__cluster_id__approvals__approval_id__decision_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "approval_id",
      "required": true,
      "schema": {
       "title": "Approval Id",
       "type": "string"
      },
      "description": "Identifier of the approval request."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DecisionBody"
       }
      }
     },
     "required": true,
     "description": "The decision."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Decide Approval Api V1 Clusters  Cluster Id  Approvals  Approval Id  Decision Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Approve or reject an approval request",
    "tags": [
     "lifecycle"
    ],
    "description": "Decides a pending request; the requester cannot decide its own. Returns the approval. Permission `cluster:manage`. Errors: `404 approval_invalid`, `409 approval_not_pending`, `403 approval_self`. Audited as `approval.approve` or `approval.reject`."
   }
  },
  "/api/v1/clusters/{cluster_id}/backups": {
   "get": {
    "operationId": "list_backups_api_v1_clusters__cluster_id__backups_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "service",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Service"
      },
      "description": "Only the backups of this service."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Backups Api V1 Clusters  Cluster Id  Backups Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the service backups of a cluster",
    "tags": [
     "lifecycle"
    ],
    "description": "Returns `backupable` (the installed services whose catalog declares a backup) and the last 300 backups with their service, host, set, status, files and digests. Permission `cluster:read`."
   },
   "post": {
    "operationId": "create_backup_api_v1_clusters__cluster_id__backups_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BackupBody"
       }
      }
     },
     "required": true,
     "description": "Services to back up."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Backup Api V1 Clusters  Cluster Id  Backups Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Take a coordinated backup",
    "tags": [
     "lifecycle"
    ],
    "description": "Starts one operation that backs up the services given (every backupable service by default) in dependency order, sharing one `set_id`; the set succeeds only when every member succeeded. Returns `operation_id`, `set_id` and `backup_ids`. Permission `services:operate`. Audited as `backup.create`."
   }
  },
  "/api/v1/clusters/{cluster_id}/backups/{backup_id}/restore": {
   "post": {
    "operationId": "restore_backup_api_v1_clusters__cluster_id__backups__backup_id__restore_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "backup_id",
      "required": true,
      "schema": {
       "title": "Backup Id",
       "type": "string"
      },
      "description": "Identifier of the service backup."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ApprovalOnly"
       }
      }
     },
     "required": true,
     "description": "Optional approval."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Restore Backup Api V1 Clusters  Cluster Id  Backups  Backup Id  Restore Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Restore a service backup",
    "tags": [
     "lifecycle"
    ],
    "description": "Starts the restore operation: stop the instances, check the digests, run the restore steps, start the instances, run the health checks, the verify steps, the service check and the smoke test. Returns `operation_id`. Permission `services:install`; an approval under `banking-secure`. Audited as `backup.restore`."
   }
  },
  "/api/v1/clusters/{cluster_id}/blueprint": {
   "get": {
    "operationId": "export_blueprint_api_v1_clusters__cluster_id__blueprint_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Export Blueprint Api V1 Clusters  Cluster Id  Blueprint Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Export the blueprint of a cluster",
    "tags": [
     "blueprint"
    ],
    "description": "Returns the blueprint of the cluster: its managed services with their non secret configuration (secrets are never exported) and host groups built from the components that run together; `hosts` of a group lists the hosts of this cluster for information. Permission `cluster:manage`."
   }
  },
  "/api/v1/clusters/{cluster_id}/blueprint/apply": {
   "post": {
    "operationId": "apply_blueprint_api_v1_clusters__cluster_id__blueprint_apply_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__blueprint__ApplyBody"
       }
      }
     },
     "required": true,
     "description": "Blueprint, host mapping and install options."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Apply Blueprint Api V1 Clusters  Cluster Id  Blueprint Apply Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Apply a blueprint to a cluster",
    "tags": [
     "blueprint"
    ],
    "description": "Turns the blueprint and the host mapping into install requests and creates one install operation (type `blueprint.apply`), with the same checks as a service install. Returns `operation_id` and the `ha` checks. Permissions `cluster:manage` and `services:install`. Errors: `422 blueprint_invalid` (with `details.errors`), and the errors of an install. Audited as `blueprint.apply`."
   }
  },
  "/api/v1/clusters/{cluster_id}/blueprint/validate": {
   "post": {
    "operationId": "validate_blueprint_api_v1_clusters__cluster_id__blueprint_validate_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ValidateBody"
       }
      }
     },
     "required": true,
     "description": "Blueprint and optional host mapping."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Validate Blueprint Api V1 Clusters  Cluster Id  Blueprint Validate Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Validate a blueprint for a cluster",
    "tags": [
     "blueprint"
    ],
    "description": "Checks the shape of the blueprint and, when a `host_mapping` is given, the mapping and the resulting install requests. Returns `ok` and `errors` (each with `service`, `field`, `code`, `message_i18n`). Nothing is changed. Permission `cluster:manage`."
   }
  },
  "/api/v1/clusters/{cluster_id}/bootstrap-tokens": {
   "get": {
    "operationId": "list_tokens_api_v1_clusters__cluster_id__bootstrap_tokens_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Tokens Api V1 Clusters  Cluster Id  Bootstrap Tokens Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the bootstrap tokens of a cluster",
    "tags": [
     "clusters"
    ],
    "description": "Tokens of the cluster, newest first, with `prefix`, `expires_at`, `max_uses`, `uses`, `created_at` and `revoked_at`; the secret is never returned. Permission `hosts:manage`."
   },
   "post": {
    "operationId": "create_token_api_v1_clusters__cluster_id__bootstrap_tokens_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TokenIn"
       }
      }
     },
     "required": true,
     "description": "Lifetime and number of uses of the token."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Token Api V1 Clusters  Cluster Id  Bootstrap Tokens Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create a bootstrap token for new hosts",
    "tags": [
     "clusters"
    ],
    "description": "Creates a token that lets agents register in this cluster and returns `id`, `token` (shown only here),\n`expires_at`, `register_command` (the `nm-agent register` command with the server URL, the token and the\nfingerprint of the CA) and `install_command` (a script that installs the agent from the mirror and registers\nit). Answers `201`. Permission `hosts:manage`. Audited as `bootstrap_token.create`."
   }
  },
  "/api/v1/clusters/{cluster_id}/bootstrap-tokens/{token_id}": {
   "delete": {
    "operationId": "revoke_token_api_v1_clusters__cluster_id__bootstrap_tokens__token_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "token_id",
      "required": true,
      "schema": {
       "title": "Token Id",
       "type": "string"
      },
      "description": "Identifier of the bootstrap token."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Revoke a bootstrap token",
    "tags": [
     "clusters"
    ],
    "description": "Revokes the token: no new agent can register with it; hosts already registered are not affected. Answers `204`. Permission `hosts:manage`; `404 bootstrap_token_not_found` (unknown or already revoked). Audited as `bootstrap_token.revoke`."
   }
  },
  "/api/v1/clusters/{cluster_id}/certificates": {
   "get": {
    "operationId": "list_certificates_api_v1_clusters__cluster_id__certificates_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Certificates Api V1 Clusters  Cluster Id  Certificates Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the certificates of a cluster",
    "tags": [
     "pki"
    ],
    "description": "Certificates issued for the cluster, the first to expire first: `kind` (`agent` or `service`), host, service, component, `serial`, `subject`, `sans`, `not_before`, `not_after`, `revoked_at`. Permission `cluster:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/certificates/rotate": {
   "post": {
    "operationId": "rotate_api_v1_clusters__cluster_id__certificates_rotate_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "approval_id",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Approval Id"
      }
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RotateIn"
       }
      }
     },
     "required": true,
     "description": "Optional service to limit the rotation to."
    },
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Rotate Api V1 Clusters  Cluster Id  Certificates Rotate Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Rotate the service certificates of a cluster",
    "tags": [
     "pki"
    ],
    "description": "Issues a new certificate for every component instance (of one service, or of all), then starts an operation that installs them on the hosts and restarts the components. Answers `202` with `operation_id`. Permission `pki:manage`. Errors: `404 cluster_not_found`, `409 no_certificates_to_rotate`. Audited as `pki.rotate`."
   }
  },
  "/api/v1/clusters/{cluster_id}/consoles": {
   "get": {
    "operationId": "list_consoles_api_v1_clusters__cluster_id__consoles_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Consoles Api V1 Clusters  Cluster Id  Consoles Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the service consoles of a cluster",
    "tags": [
     "consoles"
    ],
    "description": "Every console of the catalog with its state on the cluster: installed or not, health, internal address, compliance checks, whether the caller may open it and, for the vault administrators, the vault entry holding its credentials. Services without a web interface are listed apart with their HTTP endpoints. Permission `services:operate`. Audited as `consoles.list`."
   }
  },
  "/api/v1/clusters/{cluster_id}/consoles/{service}/access": {
   "put": {
    "operationId": "put_access_api_v1_clusters__cluster_id__consoles__service__access_put",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AccessBody"
       }
      }
     },
     "required": true,
     "description": "Published address and protection."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Put Access Api V1 Clusters  Cluster Id  Consoles  Service  Access Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Publish the internal address of a console",
    "tags": [
     "consoles"
    ],
    "description": "Sets the internal address of the console (behind the HTTPS gateway of the bank) and its protection; both null go back to the discovered address. Returns the console; the vault entry of the service is updated with the new address. Permission `cluster:manage`; `422 console_url_invalid`. Audited as `console.access`."
   }
  },
  "/api/v1/clusters/{cluster_id}/consoles/{service}/credentials/rotate": {
   "post": {
    "operationId": "rotate_credentials_api_v1_clusters__cluster_id__consoles__service__credentials_rotate_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RotateBody"
       }
      }
     },
     "required": true,
     "description": "New password and restart policy."
    },
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Rotate Credentials Api V1 Clusters  Cluster Id  Consoles  Service  Credentials Rotate Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Rotate the password of a console account",
    "tags": [
     "consoles"
    ],
    "description": "Sets a new password (generated when omitted) for the console account read from the configuration: creates a new configuration version and starts the apply operation; the vault entry follows when the apply succeeds. Answers `202` with `operation_id` and `version`. The password is never logged. Permissions `configs:edit` and `vault:manage`. Errors: `409 console_no_credential`, `409 console_rotation_manual`, `409 service_unmanaged`, `422 config_invalid`. Audited as `console.credentials.rotate`."
   }
  },
  "/api/v1/clusters/{cluster_id}/consoles/{service}/open": {
   "post": {
    "operationId": "open_console_api_v1_clusters__cluster_id__consoles__service__open_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Open Console Api V1 Clusters  Cluster Id  Consoles  Service  Open Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Open a service console",
    "tags": [
     "consoles"
    ],
    "description": "Returns `url`, the `checks` and `compliant`. Needs `services:operate` and the permission of the console (`vault:manage` for an identity or secrets console). Errors: `404 console_unknown`, `409 console_not_installed`, `409 console_no_url`, `409 console_not_compliant` (production or pre-production). Audited as `console.open`."
   }
  },
  "/api/v1/clusters/{cluster_id}/drift": {
   "get": {
    "operationId": "drift_report_api_v1_clusters__cluster_id__drift_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "resolved",
      "required": false,
      "schema": {
       "default": false,
       "title": "Resolved",
       "type": "boolean"
      },
      "description": "Also return the resolved findings. Default false."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Drift Report Api V1 Clusters  Cluster Id  Drift Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the drift report of a cluster",
    "tags": [
     "lifecycle"
    ],
    "description": "Findings of the last scans: managed files and units changed, removed or replaced outside the Manager, with host, service, component and path. Open findings raise the `config_drift` alert. Permission `cluster:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/drift/scan": {
   "post": {
    "operationId": "drift_scan_api_v1_clusters__cluster_id__drift_scan_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ScanBody"
       }
      }
     },
     "required": true,
     "description": "Hosts to scan."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Drift Scan Api V1 Clusters  Cluster Id  Drift Scan Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Scan the cluster for drift",
    "tags": [
     "lifecycle"
    ],
    "description": "Starts an operation with one digest task per host over the files and units the Manager wrote; differences open findings. Returns `operation_id`. Permission `services:operate`. Audited as `drift.scan`."
   }
  },
  "/api/v1/clusters/{cluster_id}/drift/{finding_id}/reconcile": {
   "post": {
    "description": "Rewrites the files and units of the drifted instance from the Manager configuration (and restarts it when asked). Returns `operation_id`. Permission `configs:edit`. Errors: `404 drift_not_found`, `409 drift_not_reconcilable` (a file that belongs to no service). Audited as `drift.reconcile`.",
    "operationId": "drift_reconcile_api_v1_clusters__cluster_id__drift__finding_id__reconcile_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "finding_id",
      "required": true,
      "schema": {
       "title": "Finding Id",
       "type": "string"
      },
      "description": "Identifier of the drift finding."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReconcileBody"
       }
      }
     },
     "required": true,
     "description": "Restart option and optional approval."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Drift Reconcile Api V1 Clusters  Cluster Id  Drift  Finding Id  Reconcile Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Reconcile a drift finding",
    "tags": [
     "lifecycle"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/hosts": {
   "get": {
    "operationId": "list_hosts_api_v1_clusters__cluster_id__hosts_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Hosts Api V1 Clusters  Cluster Id  Hosts Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the hosts of a cluster",
    "tags": [
     "hosts"
    ],
    "description": "Hosts of the cluster sorted by hostname, with their state, operating system, resources, labels, components, open alerts, agent version, certificate expiry, latest metrics and network rates. Permission `cluster:read`; `404 cluster_not_found`."
   }
  },
  "/api/v1/clusters/{cluster_id}/hosts/ssh-bootstrap": {
   "post": {
    "description": "Starts an operation with one task per host: the Manager connects over SSH (the host key must match the\nfingerprint given), installs the agent and registers it with a bootstrap token created for this operation\n(valid 2 hours, one use per host). The private key is kept in memory for the tasks only, never stored nor\nlogged. A failed host does not stop the others. Answers `202` with `operation_id`. Permission `hosts:manage`.\nErrors: `422 validation_error` (invalid name or missing fingerprint), `404 cluster_not_found`. Audited as\n`host.ssh_bootstrap`.",
    "operationId": "ssh_bootstrap_api_v1_clusters__cluster_id__hosts_ssh_bootstrap_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SshBootstrapIn"
       }
      }
     },
     "required": true,
     "description": "Hosts, SSH account, private key and host key fingerprints."
    },
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Ssh Bootstrap Api V1 Clusters  Cluster Id  Hosts Ssh Bootstrap Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Install agents over SSH",
    "tags": [
     "hosts"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/kubernetes": {
   "delete": {
    "operationId": "unregister_api_v1_clusters__cluster_id__kubernetes_delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Unregister a Kubernetes cluster",
    "tags": [
     "kubernetes"
    ],
    "description": "Forgets the API server and the kubeconfig; the cluster becomes a host cluster again. Refused while components remain (`409 k8s_components_remain`). Answers `204`. Permission `cluster:manage`. Audited as `k8s.cluster.unregister`."
   },
   "get": {
    "operationId": "get_target_api_v1_clusters__cluster_id__kubernetes_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Target Api V1 Clusters  Cluster Id  Kubernetes Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a Kubernetes target",
    "tags": [
     "kubernetes"
    ],
    "description": "Returns the API server, the namespace, the server version, the discovered mode, distribution and number of nodes, the discovery time, the last error and the kubeconfig as `{\"secret\": true, \"set\": true}`. Permission `cluster:read`."
   },
   "patch": {
    "operationId": "patch_target_api_v1_clusters__cluster_id__kubernetes_patch",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__kubernetes__TargetPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the target to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Patch Target Api V1 Clusters  Cluster Id  Kubernetes Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update a Kubernetes target",
    "tags": [
     "kubernetes"
    ],
    "description": "Changes the API server, the kubeconfig (send the read back object to keep it) or the namespace (refused while components remain); the kubeconfig guard runs again. Permission `cluster:manage`. Errors: `422 validation_error`, `409 k8s_components_remain`. Audited as `k8s.cluster.update`."
   },
   "post": {
    "operationId": "register_api_v1_clusters__cluster_id__kubernetes_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__kubernetes__TargetIn"
       }
      }
     },
     "required": true,
     "description": "API server, kubeconfig and namespace."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Register Api V1 Clusters  Cluster Id  Kubernetes Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Register a Kubernetes cluster",
    "tags": [
     "kubernetes"
    ],
    "description": "Checks the kubeconfig against the API server given, calls `/version`, seals the kubeconfig and turns the cluster into a Kubernetes cluster. The cluster must have no host. Returns the target (`201`). Permission `cluster:manage`. Errors: `409 k8s_already_registered`, `409 k8s_cluster_has_hosts`, kubeconfig guard and API errors. Audited as `k8s.cluster.register`."
   }
  },
  "/api/v1/clusters/{cluster_id}/kubernetes/agent": {
   "delete": {
    "operationId": "revoke_api_v1_clusters__cluster_id__kubernetes_agent_delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Revoke the cluster agent identity",
    "tags": [
     "kubernetes"
    ],
    "description": "Revokes the identity of the Navin Cluster Agent. Answers `204`. Permission `cluster:manage`; `404 k8s_agent_not_registered`. Audited as `k8s.agent.revoke`."
   },
   "get": {
    "operationId": "get_agent_api_v1_clusters__cluster_id__kubernetes_agent_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Agent Api V1 Clusters  Cluster Id  Kubernetes Agent Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the cluster agent",
    "tags": [
     "kubernetes"
    ],
    "description": "State of the identity of the Navin Cluster Agent and its last report. Permission `cluster:read`."
   },
   "post": {
    "operationId": "issue_api_v1_clusters__cluster_id__kubernetes_agent_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AgentIn"
       }
      }
     },
     "required": true,
     "description": "Gateway URL, tenant and offline delay of the agent."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Issue Api V1 Clusters  Cluster Id  Kubernetes Agent Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Issue the cluster agent identity",
    "tags": [
     "kubernetes"
    ],
    "description": "Issues the client certificate and the configuration of the Navin Cluster Agent: `certificate_pem`, `private_key_pem` (returned once, never stored), `ca_pem`, `manager_public_key_pem`, `config`, `fingerprint` and `not_after` (`201`). Permission `cluster:manage`; `422 k8s_agent_gateway_url_invalid`. Audited as `k8s.agent.issue`."
   }
  },
  "/api/v1/clusters/{cluster_id}/kubernetes/agent/commands": {
   "get": {
    "operationId": "list_commands_api_v1_clusters__cluster_id__kubernetes_agent_commands_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Commands Api V1 Clusters  Cluster Id  Kubernetes Agent Commands Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the cluster agent commands",
    "tags": [
     "kubernetes"
    ],
    "description": "The last 200 commands queued for the cluster agent, each with its receipts. Permission `cluster:read`."
   },
   "post": {
    "operationId": "queue_command_api_v1_clusters__cluster_id__kubernetes_agent_commands_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__k8s_agents__CommandIn"
       }
      }
     },
     "required": true,
     "description": "Operation, parameters, idempotency key and validity."
    },
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Queue Command Api V1 Clusters  Cluster Id  Kubernetes Agent Commands Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Queue a signed command for the cluster agent",
    "tags": [
     "kubernetes"
    ],
    "description": "Records the authorization decision, then queues a signed command (`managedcomponent.apply`, `managedcomponent.delete` or `inventory.report`) the agent picks up. Answers `202` with the command. Permission `services:operate`. Audited as `k8s.agent.policy`."
   }
  },
  "/api/v1/clusters/{cluster_id}/kubernetes/agent/manifests": {
   "get": {
    "operationId": "agent_manifests_api_v1_clusters__cluster_id__kubernetes_agent_manifests_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "image",
      "required": true,
      "schema": {
       "pattern": "^[A-Za-z0-9.:/_-]+(@sha256:[a-f0-9]{64})$",
       "title": "Image",
       "type": "string"
      },
      "description": "Image of the agent pinned by digest, for example `<registry-host>/navin/cluster-agent@sha256:<64 hex>`."
     },
     {
      "in": "query",
      "name": "replicas",
      "required": false,
      "schema": {
       "default": 2,
       "maximum": 5,
       "minimum": 2,
       "title": "Replicas",
       "type": "integer"
      },
      "description": "Replicas of the agent Deployment (leader election), 2 to 5. Default 2."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Agent Manifests Api V1 Clusters  Cluster Id  Kubernetes Agent Manifests Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the manifests of the cluster agent",
    "tags": [
     "kubernetes"
    ],
    "description": "ServiceAccount, RBAC and Deployment of the cluster agent for the managed namespace, as objects (`manifests`) and as YAML (`yaml`) ready for `kubectl apply`. Permission `cluster:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/kubernetes/components": {
   "get": {
    "description": "Live list: every `ManagedComponent` of the namespace with its status, which is also written into the model of the Manager. Permission `cluster:read`.",
    "operationId": "list_components_api_v1_clusters__cluster_id__kubernetes_components_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Components Api V1 Clusters  Cluster Id  Kubernetes Components Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the Kubernetes components",
    "tags": [
     "kubernetes"
    ]
   },
   "post": {
    "operationId": "install_component_api_v1_clusters__cluster_id__kubernetes_components_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ComponentIn"
       }
      }
     },
     "required": true,
     "description": "Service, source, values, replicas and policies of the component."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Install Component Api V1 Clusters  Cluster Id  Kubernetes Components Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Install a catalog service on Kubernetes",
    "tags": [
     "kubernetes"
    ],
    "description": "Creates the `ManagedComponent` resource of a catalog service (chart from a path or an OCI reference pinned by digest) and returns its state (`201`). Values that look like secrets are refused. Permission `services:install`. Errors: `409 k8s_component_exists`, `422 k8s_values_secret`, `409 k8s_replicas_below_pdb`. Audited as `k8s.component.install`."
   }
  },
  "/api/v1/clusters/{cluster_id}/kubernetes/components/{name}": {
   "delete": {
    "operationId": "remove_component_api_v1_clusters__cluster_id__kubernetes_components__name__delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "name",
      "required": true,
      "schema": {
       "maxLength": 63,
       "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
       "title": "Name",
       "type": "string"
      },
      "description": "Name of the component (the `ManagedComponent` resource)."
     }
    ],
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Remove Component Api V1 Clusters  Cluster Id  Kubernetes Components  Name  Delete",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Remove a Kubernetes component",
    "tags": [
     "kubernetes"
    ],
    "description": "Deletes the `ManagedComponent` resource; the operator uninstalls the chart. Answers `202` with `{\"name\", \"state\": \"removed\"}` once the resource is gone, else the component still being deleted. Permission `services:install`. Errors: `404 k8s_component_not_found`, `409 k8s_maintenance`. Audited as `k8s.component.remove`."
   },
   "get": {
    "operationId": "get_component_api_v1_clusters__cluster_id__kubernetes_components__name__get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "name",
      "required": true,
      "schema": {
       "maxLength": 63,
       "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
       "title": "Name",
       "type": "string"
      },
      "description": "Name of the component."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Component Api V1 Clusters  Cluster Id  Kubernetes Components  Name  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a Kubernetes component",
    "tags": [
     "kubernetes"
    ],
    "description": "Reads the resource and returns its observed state. Permission `cluster:read`; `404 k8s_component_not_found` (the record is dropped when the resource is gone)."
   },
   "patch": {
    "operationId": "configure_component_api_v1_clusters__cluster_id__kubernetes_components__name__patch",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "name",
      "required": true,
      "schema": {
       "maxLength": 63,
       "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
       "title": "Name",
       "type": "string"
      },
      "description": "Name of the component."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ComponentPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the component to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Configure Component Api V1 Clusters  Cluster Id  Kubernetes Components  Name  Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Configure a Kubernetes component",
    "tags": [
     "kubernetes"
    ],
    "description": "Changes the version, source, values, secret references or disruption budget of the component (server side apply). Values that look like secrets are refused: use `secret_refs`. Permission `configs:edit`. Errors: `422 k8s_values_secret`, `409 k8s_maintenance`, `404 k8s_component_not_found`. Audited as `k8s.component.configure` (field names only)."
   }
  },
  "/api/v1/clusters/{cluster_id}/kubernetes/components/{name}/actions": {
   "post": {
    "operationId": "component_action_api_v1_clusters__cluster_id__kubernetes_components__name__actions_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "name",
      "required": true,
      "schema": {
       "maxLength": 63,
       "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
       "title": "Name",
       "type": "string"
      },
      "description": "Name of the component."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ActionIn"
       }
      }
     },
     "required": true,
     "description": "Action and its arguments."
    },
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Component Action Api V1 Clusters  Cluster Id  Kubernetes Components  Name  Actions Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run an action on a Kubernetes component",
    "tags": [
     "kubernetes"
    ],
    "description": "Changes the desired state: `start`, `stop`, `restart` or `rolling_restart` (a restart timestamp), `scale` (fixed `replicas` or `autoscaling`, never below the disruption budget) or `maintenance` (`enabled`). Answers `202` with `component` and `requested`. Permission `services:operate`. Errors: `409 k8s_maintenance`, `409 k8s_component_stopped`, `409 k8s_replicas_below_pdb`. Audited as `k8s.component.<action>`."
   }
  },
  "/api/v1/clusters/{cluster_id}/kubernetes/discovery": {
   "get": {
    "operationId": "last_discovery_api_v1_clusters__cluster_id__kubernetes_discovery_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Last Discovery Api V1 Clusters  Cluster Id  Kubernetes Discovery Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the last discovery of a Kubernetes cluster",
    "tags": [
     "kubernetes"
    ],
    "description": "Returns the inventory of the last discovery. Permission `cluster:read`; `404 k8s_not_discovered`."
   },
   "post": {
    "operationId": "run_discovery_api_v1_clusters__cluster_id__kubernetes_discovery_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Run Discovery Api V1 Clusters  Cluster Id  Kubernetes Discovery Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Discover a Kubernetes cluster",
    "tags": [
     "kubernetes"
    ],
    "description": "Reads, with read only calls, the version, the distribution (bring your own or managed), the nodes with their capacity and GPUs, the storage and ingress classes, CoreDNS and the platform add-ons (cert-manager, Cilium, Kyverno, Argo CD, KEDA...). Stores and returns the inventory. Permission `hosts:manage`. Audited as `k8s.discovery`."
   }
  },
  "/api/v1/clusters/{cluster_id}/kubernetes/import-rbac": {
   "get": {
    "operationId": "import_rbac_api_v1_clusters__cluster_id__kubernetes_import_rbac_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "namespace",
      "required": false,
      "schema": {
       "default": "navin-platform",
       "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
       "title": "Namespace",
       "type": "string"
      },
      "description": "Managed namespace. Default `navin-platform`."
     },
     {
      "in": "query",
      "name": "identity",
      "required": false,
      "schema": {
       "default": "navin-import",
       "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
       "title": "Identity",
       "type": "string"
      },
      "description": "Name of the ServiceAccount of the import. Default `navin-import`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Import Rbac Api V1 Clusters  Cluster Id  Kubernetes Import Rbac Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the RBAC of the import identity",
    "tags": [
     "kubernetes"
    ],
    "description": "Least privilege RBAC of the identity the Manager uses for the cluster, as objects and YAML, with the resulting user name: read what the discovery needs, write only `platform.navin.ai` resources in the managed namespace; no Secret, RBAC object, workload, exec nor impersonation. Permission `cluster:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/mcp-runtime": {
   "get": {
    "description": "Returns the `operator` state (with `crd_installed`), the ToolHive `components`, the `preset`, the managed instances `items` (filtered by `tenant` and `project`), the `ignored` objects, the `aggregates` by tenant and project (always over every managed instance) and `observed_at`. Permission `cluster:read`.",
    "operationId": "runtime_state_api_v1_clusters__cluster_id__mcp_runtime_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "tenant",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 63,
         "pattern": "^[A-Za-z0-9]([-A-Za-z0-9_.]{0,61}[A-Za-z0-9])?$",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Tenant"
      },
      "description": "Only the instances of this tenant (label value, at most 63 characters)."
     },
     {
      "in": "query",
      "name": "project",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 63,
         "pattern": "^[A-Za-z0-9]([-A-Za-z0-9_.]{0,61}[A-Za-z0-9])?$",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Project"
      },
      "description": "Only the instances of this project (label value, at most 63 characters)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Runtime State Api V1 Clusters  Cluster Id  Mcp Runtime Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the MCP runtime state",
    "tags": [
     "mcp-runtime"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/mcp-runtime/install": {
   "post": {
    "description": "Writes the two `ManagedComponent` resources of ToolHive (CRDs, then operator) in `toolhive-system`, pinned by digest. Returns `namespace`, `version` and the `components` written (`201`). Permission `services:install`; `409 mcp_runtime_installed`. Audited as `mcp_runtime.install`.",
    "operationId": "install_toolhive_api_v1_clusters__cluster_id__mcp_runtime_install_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Install Toolhive Api V1 Clusters  Cluster Id  Mcp Runtime Install Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Install the ToolHive operator",
    "tags": [
     "mcp-runtime"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/mcp-runtime/instances/{namespace}/{name}": {
   "delete": {
    "description": "Deletes one managed `MCPServer` (uid precondition); the Control Plane controller then revokes its credentials and closes it. Returns `namespace`, `name`, `instance_id` and `state` (`deleting`). Permission `services:operate`. Errors: `404 mcp_runtime_instance_not_found`, `502 mcp_runtime_forbidden` (the identity of the Manager lacks the right). Audited as `mcp_runtime.instance.destroy`.",
    "operationId": "destroy_instance_api_v1_clusters__cluster_id__mcp_runtime_instances__namespace___name__delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "namespace",
      "required": true,
      "schema": {
       "title": "Namespace",
       "type": "string"
      },
      "description": "Project namespace of the instance, `mcp-<12 hex>`."
     },
     {
      "in": "path",
      "name": "name",
      "required": true,
      "schema": {
       "title": "Name",
       "type": "string"
      },
      "description": "Name of the `MCPServer` object."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Destroy Instance Api V1 Clusters  Cluster Id  Mcp Runtime Instances  Namespace   Name  Delete",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete a managed MCP instance",
    "tags": [
     "mcp-runtime"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/mcp-runtime/instances/{namespace}/{name}/restart": {
   "post": {
    "description": "Restarts one managed `MCPServer` without changing its spec: a merge patch of the annotation `mcpserver.toolhive.stacklok.dev/restarted-at` to a new RFC 3339 time (rolling restart by the operator), with the uid as precondition. Returns `namespace`, `name`, `instance_id`, `state` (`restarting`) and `restarted_at`. Permission `services:operate`; `404 mcp_runtime_instance_not_found`. Audited as `mcp_runtime.instance.restart`.",
    "operationId": "restart_instance_api_v1_clusters__cluster_id__mcp_runtime_instances__namespace___name__restart_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "namespace",
      "required": true,
      "schema": {
       "title": "Namespace",
       "type": "string"
      },
      "description": "Project namespace of the instance, `mcp-<12 hex>`."
     },
     {
      "in": "path",
      "name": "name",
      "required": true,
      "schema": {
       "title": "Name",
       "type": "string"
      },
      "description": "Name of the `MCPServer` object."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Restart Instance Api V1 Clusters  Cluster Id  Mcp Runtime Instances  Namespace   Name  Restart Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Restart a managed MCP instance",
    "tags": [
     "mcp-runtime"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/network/flows": {
   "get": {
    "description": "Flows to open between the hosts, the Manager, the clients and the external endpoints of the cluster. JSON: `cluster_id`, `items`, `summary` and `generated_at`; with `format=csv`, a `network-flows-<cluster>.csv` attachment. Permission `cluster:read`.",
    "operationId": "network_flows_api_v1_clusters__cluster_id__network_flows_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "format",
      "required": false,
      "schema": {
       "default": "json",
       "enum": [
        "json",
        "csv"
       ],
       "title": "Format",
       "type": "string"
      },
      "description": "Answer format: `json` (default) or `csv`."
     },
     {
      "in": "query",
      "name": "service",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 100,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Service"
      },
      "description": "Only the flows of this service."
     },
     {
      "in": "query",
      "name": "host_id",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 64,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Host Id"
      },
      "description": "Only the flows from or to this host."
     },
     {
      "in": "query",
      "name": "scope",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "enum": [
          "platform",
          "service",
          "intra_service",
          "egress"
         ],
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Scope"
      },
      "description": "Only the flows of this scope: `platform`, `service`, `intra_service` or `egress`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {}
       },
       "text/csv": {
        "schema": {
         "type": "string"
        }
       }
      },
      "description": "The flows; text/csv attachment with format=csv."
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the network flow matrix of a cluster",
    "tags": [
     "network"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/network/rules": {
   "get": {
    "description": "Commands opening the flows in the security groups of a cloud provider or in a host firewall. With `auto`, the provider of each host is used (the environment chosen for the host, else the detected platform). Nothing is applied. Permission `cluster:read`.",
    "operationId": "network_rules_api_v1_clusters__cluster_id__network_rules_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "provider",
      "required": true,
      "schema": {
       "enum": [
        "auto",
        "aws",
        "azure",
        "gcp",
        "ibm",
        "openstack",
        "ovh",
        "firewalld",
        "ufw"
       ],
       "title": "Provider",
       "type": "string"
      },
      "description": "Target of the rules: `auto`, `aws`, `azure`, `gcp`, `ibm`, `openstack`, `ovh`, `firewalld` or `ufw`."
     },
     {
      "in": "query",
      "name": "service",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 100,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Service"
      },
      "description": "Only the flows of this service."
     },
     {
      "in": "query",
      "name": "host_id",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 64,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Host Id"
      },
      "description": "Only the flows from or to this host."
     },
     {
      "in": "query",
      "name": "scope",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "enum": [
          "platform",
          "service",
          "intra_service",
          "egress"
         ],
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Scope"
      },
      "description": "Only the flows of this scope: `platform`, `service`, `intra_service` or `egress`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Network Rules Api V1 Clusters  Cluster Id  Network Rules Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the firewall rules that open the flows",
    "tags": [
     "network"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/operations": {
   "get": {
    "operationId": "list_operations_api_v1_clusters__cluster_id__operations_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "status",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "pattern": "^(pending|running|succeeded|failed|aborted)$",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Status"
      },
      "description": "Only the operations in this status: `pending`, `running`, `succeeded`, `failed` or `aborted`."
     },
     {
      "in": "query",
      "name": "limit",
      "required": false,
      "schema": {
       "default": 50,
       "maximum": 500,
       "minimum": 1,
       "title": "Limit",
       "type": "integer"
      },
      "description": "Maximum number of operations in the page, from 1 to 500. Default 50."
     },
     {
      "in": "query",
      "name": "cursor",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Cursor"
      },
      "description": "The `next_cursor` of the previous page (an operation identifier). Omit it for the first page."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Operations Api V1 Clusters  Cluster Id  Operations Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the operations of a cluster",
    "tags": [
     "operations"
    ],
    "description": "Operations of the cluster, newest first, without their stages: `id`, `type`, `title_i18n`, `target`, `status`, `progress`, `error`, `created_by`, `created_at`, `started_at`, `finished_at`, `abort_requested`. Paginated with `limit` and `cursor`. Permission `operations:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/preflight": {
   "post": {
    "operationId": "run_preflight_api_v1_clusters__cluster_id__preflight_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PreflightBody"
       }
      }
     },
     "required": true,
     "description": "Services and hosts to check."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Run Preflight Api V1 Clusters  Cluster Id  Preflight Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run the installation preflight of a cluster",
    "tags": [
     "lifecycle"
    ],
    "description": "Every check that must pass before a service is installed or upgraded, with its severity, evidence and a blocking verdict: host facts, DNS, catalog preflight entries, firewall, capacity, versions, TLS and profile rules. A check in `fail` blocks. Nothing is changed. Permission `services:install`."
   }
  },
  "/api/v1/clusters/{cluster_id}/profile": {
   "get": {
    "description": "Every rule of the cluster profile (or of `profile`, to compare before choosing one) evaluated against the real state, each with `status` (`pass` or `fail`), label and reason; the status is blocked when one rule fails. Permission `cluster:read`.",
    "operationId": "cluster_profile_api_v1_clusters__cluster_id__profile_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "query",
      "name": "profile",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Profile"
      },
      "description": "Profile to evaluate instead of the current one: `development`, `standard`, `banking-secure`, `air-gapped` or `hybrid`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Cluster Profile Api V1 Clusters  Cluster Id  Profile Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Evaluate the profile of a cluster",
    "tags": [
     "lifecycle"
    ]
   },
   "put": {
    "operationId": "set_profile_api_v1_clusters__cluster_id__profile_put",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ProfileBody"
       }
      }
     },
     "required": true,
     "description": "The new profile."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Set Profile Api V1 Clusters  Cluster Id  Profile Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Change the profile of a cluster",
    "tags": [
     "lifecycle"
    ],
    "description": "Sets the installation profile and returns its evaluation. Permission `cluster:manage`. Audited as `cluster.profile` with the previous and the new profile."
   }
  },
  "/api/v1/clusters/{cluster_id}/sd/prometheus": {
   "get": {
    "operationId": "prometheus_sd_api_v1_clusters__cluster_id__sd_prometheus_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response Prometheus Sd Api V1 Clusters  Cluster Id  Sd Prometheus Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Prometheus service discovery of a cluster",
    "tags": [
     "system"
    ],
    "description": "Targets in the Prometheus HTTP service discovery format: one group per component instance exposing metrics, with `targets` (`fqdn:port`) and the labels `__metrics_path__`, `__scheme__`, `nm_cluster`, `nm_service`, `nm_component`, `nm_host`. Permission `cluster:read`; `404 cluster_not_found`."
   }
  },
  "/api/v1/clusters/{cluster_id}/security-lock": {
   "delete": {
    "operationId": "unlock_cluster_api_v1_clusters__cluster_id__security_lock_delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Unlock Cluster Api V1 Clusters  Cluster Id  Security Lock Delete",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Lift the security lock of a cluster",
    "tags": [
     "services"
    ],
    "description": "Lifts the lock: new operations are accepted again. Returns `cluster_id` and `security_lock` (null). Permission `pki:manage` (security role). Audited as `cluster.security_unlock`."
   },
   "post": {
    "operationId": "lock_cluster_api_v1_clusters__cluster_id__security_lock_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LockBody"
       }
      }
     },
     "required": true,
     "description": "Reason of the lock."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Lock Cluster Api V1 Clusters  Cluster Id  Security Lock Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Set the security lock of a cluster",
    "tags": [
     "services"
    ],
    "description": "Locks the cluster after a security incident: every new operation is refused with `423 cluster_security_locked`, except a security suspension or an emergency stop, until a security administrator lifts it. Returns `cluster_id` and `security_lock`. Permission `pki:manage`. Audited as `cluster.security_lock`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services": {
   "get": {
    "operationId": "list_services_api_v1_clusters__cluster_id__services_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response List Services Api V1 Clusters  Cluster Id  Services Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the services of a cluster",
    "tags": [
     "services"
    ],
    "description": "Every service of the cluster with its `display_name`, `mode`, `method`, `managed`, `state`, `health`, `version`, components and their hosts, hosts with a stale configuration, `config_version`, open alerts, administrative state, `delivery` (`install` or `connect`) and connection. Permission `cluster:read`."
   },
   "post": {
    "operationId": "install_services_api_v1_clusters__cluster_id__services_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ServicesBody"
       }
      }
     },
     "required": true,
     "description": "Services to install with their placements and configuration."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Install Services Api V1 Clusters  Cluster Id  Services Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Install services",
    "tags": [
     "services"
    ],
    "description": "Validates, gates and plans the install of one or more services, then creates the operation. Returns\n`operation_id` and the `ha` checks.\n\n1. the request is validated as with `/validate`; any error gives `422 services_invalid`, `config_invalid` or\n   `topology_invalid` (or `409 sandbox_only_service` in a production cluster);\n2. with `auto_dependencies`, the missing dependencies are added to the install;\n3. the high availability checks must pass or be acknowledged (`ha_acknowledged`);\n4. the profile and the security lock of the cluster must allow it;\n5. the operation installs the services in dependency order, configures them, starts them (`start`) and runs\n   their service check (`service_check`).\n\nPermission `services:install`. Audited as `service.install`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/connect": {
   "post": {
    "description": "Registers an existing service of yours against the `connect` section of its catalog descriptor: no host, never installed, started or stopped by the Manager. The health check and the authenticated check of the method run first; refused credentials give `422 connect_invalid`. In a production or pre-production cluster HTTPS, a verified certificate and an allowed method are required. Secret fields are sealed. Returns the service summary (`201`). Permission `services:install`. Audited as `service.connect`.",
    "operationId": "connect_service_api_v1_clusters__cluster_id__services_connect_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ConnectBody"
       }
      }
     },
     "required": true,
     "description": "Address, authentication and TLS settings of the existing service."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Connect Service Api V1 Clusters  Cluster Id  Services Connect Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Connect an existing service",
    "tags": [
     "services"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/services/connect/validate": {
   "post": {
    "description": "Dry run of a connect: checks the request against the descriptor, then runs the health check and the authenticated check of the method. Returns the verdict with the errors; nothing is saved. Permission `services:install`.",
    "operationId": "validate_connect_api_v1_clusters__cluster_id__services_connect_validate_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ConnectBody"
       }
      }
     },
     "required": true,
     "description": "Same body as a connect."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Validate Connect Api V1 Clusters  Cluster Id  Services Connect Validate Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Check a connection before saving it",
    "tags": [
     "services"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/services/validate": {
   "post": {
    "operationId": "validate_services_api_v1_clusters__cluster_id__services_validate_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ServicesBody"
       }
      }
     },
     "required": true,
     "description": "Same body as an install."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Validate Services Api V1 Clusters  Cluster Id  Services Validate Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Validate an install without running it",
    "tags": [
     "services"
    ],
    "description": "Checks an install request and previews it without changing anything. Returns `ok`, `errors` (each with `service`, `field`, `code`, `message_i18n`), `plan` (`order`, number of `stages`, `steps`), `ha` (high availability checks) and `dependencies` (`items` and `added`). Permission `services:install`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}": {
   "delete": {
    "operationId": "uninstall_service_api_v1_clusters__cluster_id__services__service__delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "query",
      "name": "purge_data",
      "required": false,
      "schema": {
       "default": false,
       "title": "Purge Data",
       "type": "boolean"
      },
      "description": "Also delete the data directories of the service. Irreversible. Default false."
     },
     {
      "in": "query",
      "name": "approval_id",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Approval Id"
      },
      "description": "Identifier of the approval granted for this uninstall (banking-secure). Omit it to use the approval granted to you, if any."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Uninstall Service Api V1 Clusters  Cluster Id  Services  Service  Delete",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Uninstall a service",
    "tags": [
     "services"
    ],
    "description": "Starts the uninstall operation (stop, remove packages and, with `purge_data`, the data) and returns `operation_id`. Permission `services:install`. Errors: `409 service_in_use` (consumers listed in `details.consumers`), `409 service_connected` (use `DELETE .../connection`), `409 approval_required` under `banking-secure`. Audited as `service.uninstall`."
   },
   "get": {
    "operationId": "get_service_api_v1_clusters__cluster_id__services__service__get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Service Api V1 Clusters  Cluster Id  Services  Service  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a service",
    "tags": [
     "services"
    ],
    "description": "The summary of the service plus its `host_components` (every instance with its state, health and version), its `bindings` to other services and its `quick_links` (web consoles rendered from the catalog). Permission `cluster:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/actions": {
   "post": {
    "operationId": "service_action_api_v1_clusters__cluster_id__services__service__actions_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ActionBody"
       }
      }
     },
     "required": true,
     "description": "Action, scope and batching."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Service Action Api V1 Clusters  Cluster Id  Services  Service  Actions Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run an action on a service",
    "tags": [
     "services"
    ],
    "description": "Starts an operation that runs the action on the components and hosts chosen (all by default) and returns `operation_id`. A rolling restart handles `batch_size` hosts at a time. `reinstall` also needs `services:install`. Permission `services:operate`. Errors: `409 service_unmanaged`, `409 service_check_missing`, `409 smoke_test_missing`, `404 host_component_not_found`, `409 approval_required`. Audited as `service.<action>`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/checks": {
   "get": {
    "operationId": "service_checks_api_v1_clusters__cluster_id__services__service__checks_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Service Checks Api V1 Clusters  Cluster Id  Services  Service  Checks Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the checks of a service",
    "tags": [
     "lifecycle"
    ],
    "description": "Liveness of every instance (health checks of the agent), readiness (service check) and functional smoke test, each with its status, results, error and time. Only a passed smoke test proves that the service works. Permission `cluster:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/client-config": {
   "get": {
    "operationId": "client_config_api_v1_clusters__cluster_id__services__service__client_config_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Client Config Api V1 Clusters  Cluster Id  Services  Service  Client Config Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the client configuration of a service",
    "tags": [
     "services"
    ],
    "description": "Files a client needs to reach the service (`path`, `content`, `mode`), rendered from the catalog with the secrets redacted. Empty `files` when the service has none. Permission `configs:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/commands/{command}": {
   "post": {
    "operationId": "service_command_api_v1_clusters__cluster_id__services__service__commands__command__post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "path",
      "name": "command",
      "required": true,
      "schema": {
       "title": "Command",
       "type": "string"
      },
      "description": "Name of the command, as declared by the catalog service."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CommandBody"
       }
      }
     },
     "required": true,
     "description": "Parameters of the command and optional target host."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Service Command Api V1 Clusters  Cluster Id  Services  Service  Commands  Command  Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run a custom command of a service",
    "tags": [
     "services"
    ],
    "description": "Starts an operation running a command declared by the catalog service (for example a vacuum or a rebalance) with its parameters and returns `operation_id`. Permission `services:operate`. Errors: `409 service_unmanaged`, `404 command_unknown`, `422 command_params_invalid`, `404 host_component_not_found`. Audited as `service.command` (parameter names only)."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/components": {
   "post": {
    "operationId": "add_component_api_v1_clusters__cluster_id__services__service__components_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ComponentBody"
       }
      }
     },
     "required": true,
     "description": "Component and target hosts."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Add Component Api V1 Clusters  Cluster Id  Services  Service  Components Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Add component instances to hosts",
    "tags": [
     "services"
    ],
    "description": "Starts an operation that installs the component on the hosts given (started unless the service is stopped) and returns `operation_id` with the `ha` checks. Permission `services:install`. Errors: `409 service_unmanaged`, `404 component_unknown`, `422 topology_invalid`, `409 ha_requirements_not_met` or `ha_acknowledgement_required`. Audited as `service.component_add`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/components/{component}/hosts/{host_id}": {
   "delete": {
    "operationId": "remove_component_api_v1_clusters__cluster_id__services__service__components__component__hosts__host_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "path",
      "name": "component",
      "required": true,
      "schema": {
       "title": "Component",
       "type": "string"
      },
      "description": "Name of the component, as declared by the catalog service, for example `server`."
     },
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     },
     {
      "in": "query",
      "name": "ha_acknowledged",
      "required": false,
      "schema": {
       "default": false,
       "title": "Ha Acknowledged",
       "type": "boolean"
      },
      "description": "Accept that the change leaves the service below its high availability requirements. Default false."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Remove Component Api V1 Clusters  Cluster Id  Services  Service  Components  Component  Hosts  Host Id  Delete",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Remove a component instance from a host",
    "tags": [
     "services"
    ],
    "description": "Starts an operation that stops and removes the component on that host and returns `operation_id` with the `ha` checks. Permission `services:install`. Errors: `404 host_component_not_found`, `422 topology_invalid` (the topology would break the rules of the service), `409 ha_requirements_not_met` or `ha_acknowledgement_required`. Audited as `service.component_remove`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/components/{component}/hosts/{host_id}/actions": {
   "post": {
    "operationId": "host_component_action_api_v1_clusters__cluster_id__services__service__components__component__hosts__host_id__actions_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "path",
      "name": "component",
      "required": true,
      "schema": {
       "title": "Component",
       "type": "string"
      },
      "description": "Name of the component."
     },
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/HostActionBody"
       }
      }
     },
     "required": true,
     "description": "Action to run."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Host Component Action Api V1 Clusters  Cluster Id  Services  Service  Components  Component  Hosts  Host Id  Actions Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run an action on one component instance",
    "tags": [
     "services"
    ],
    "description": "Like the service actions, limited to the component on one host. Returns `operation_id`. Permission `services:operate` (`services:install` for `reinstall`). Audited as `service.<action>`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/config": {
   "get": {
    "operationId": "get_config_api_v1_clusters__cluster_id__services__service__config_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Config Api V1 Clusters  Cluster Id  Services  Service  Config Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the configuration of a service",
    "tags": [
     "configs"
    ],
    "description": "Returns the current `version`, the effective `properties` (defaults merged, secrets masked), the parameter definitions `params` and `sections` of the catalog, the `recommendations` computed for the hosts, the config `groups` and the `stale_hosts`. Permission `configs:read`; `409 service_unmanaged` for a service the Manager does not manage."
   },
   "put": {
    "operationId": "put_config_api_v1_clusters__cluster_id__services__service__config_put",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ConfigBody"
       }
      }
     },
     "required": true,
     "description": "Changed properties and a note."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Put Config Api V1 Clusters  Cluster Id  Services  Service  Config Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Save a new configuration version",
    "tags": [
     "configs"
    ],
    "description": "Merges the properties sent over the current values, validates them against the parameter definitions and saves a new version. Returns `version` and `stale_hosts`. Permission `configs:edit`. Errors: `422 config_invalid` (with the fields), `409 service_unmanaged`. Audited as `config.update` (parameter names only)."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/config/apply": {
   "post": {
    "operationId": "apply_api_v1_clusters__cluster_id__services__service__config_apply_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__configs__ApplyBody"
       }
      }
     },
     "required": true,
     "description": "Restart policy of the apply."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Apply Api V1 Clusters  Cluster Id  Services  Service  Config Apply Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Apply the configuration to the hosts",
    "tags": [
     "configs"
    ],
    "description": "Starts the operation that writes the current configuration to the hosts and restarts the components as asked (`rolling` by `batch_size`, `all`, or `none`). Returns `operation_id`. Permission `configs:edit`. Under `banking-secure` an approval is needed (`409 approval_required`). Audited as `config.apply`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/config/diff": {
   "get": {
    "operationId": "diff_api_v1_clusters__cluster_id__services__service__config_diff_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "query",
      "name": "from",
      "required": true,
      "schema": {
       "minimum": 1,
       "title": "From",
       "type": "integer"
      },
      "description": "Older version number (1 or more)."
     },
     {
      "in": "query",
      "name": "to",
      "required": true,
      "schema": {
       "minimum": 1,
       "title": "To",
       "type": "integer"
      },
      "description": "Newer version number (1 or more)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response Diff Api V1 Clusters  Cluster Id  Services  Service  Config Diff Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Compare two configuration versions",
    "tags": [
     "configs"
    ],
    "description": "Lists the parameters whose value differs between the two versions, each with `param`, `secret`, `from` and `to`; for a secret only whether it is set is shown. Permission `configs:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/config/groups": {
   "get": {
    "operationId": "list_groups_api_v1_clusters__cluster_id__services__service__config_groups_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response List Groups Api V1 Clusters  Cluster Id  Services  Service  Config Groups Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the config groups of a service",
    "tags": [
     "configs"
    ],
    "description": "Every config group with its `id`, `name`, `hosts`, `overrides` (secrets masked) and `updated_at`. Permission `configs:read`."
   },
   "post": {
    "operationId": "create_group_api_v1_clusters__cluster_id__services__service__config_groups_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/GroupBody"
       }
      }
     },
     "required": true,
     "description": "Name, hosts and overrides of the group."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Group Api V1 Clusters  Cluster Id  Services  Service  Config Groups Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create a config group",
    "tags": [
     "configs"
    ],
    "description": "Creates a group of hosts with values that override the service configuration on them. A host belongs to one group at most. Permission `configs:edit`. Errors: `409 config_group_name_taken`, `409 config_group_host_conflict`, `422 config_group_host_invalid`, `422 config_invalid`. Audited as `config_group.create`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/config/groups/{group_id}": {
   "delete": {
    "operationId": "delete_group_api_v1_clusters__cluster_id__services__service__config_groups__group_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "path",
      "name": "group_id",
      "required": true,
      "schema": {
       "title": "Group Id",
       "type": "string"
      },
      "description": "Identifier of the config group."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete a config group",
    "tags": [
     "configs"
    ],
    "description": "Deletes the group; its hosts fall back to the service configuration at the next apply. Answers `204`. Permission `configs:edit`; `404 config_group_not_found`. Audited as `config_group.delete`."
   },
   "put": {
    "operationId": "update_group_api_v1_clusters__cluster_id__services__service__config_groups__group_id__put",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "path",
      "name": "group_id",
      "required": true,
      "schema": {
       "title": "Group Id",
       "type": "string"
      },
      "description": "Identifier of the config group."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/GroupBody"
       }
      }
     },
     "required": true,
     "description": "Name, hosts and overrides of the group."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Update Group Api V1 Clusters  Cluster Id  Services  Service  Config Groups  Group Id  Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update a config group",
    "tags": [
     "configs"
    ],
    "description": "Replaces the name, hosts and overrides of the group. Permission `configs:edit`. Errors: `404 config_group_not_found`, `409 config_group_name_taken`, `409 config_group_host_conflict`, `422 config_group_host_invalid`. Audited as `config_group.update`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/config/preview": {
   "get": {
    "operationId": "preview_api_v1_clusters__cluster_id__services__service__config_preview_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "query",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Host of the instance."
     },
     {
      "in": "query",
      "name": "component",
      "required": true,
      "schema": {
       "title": "Component",
       "type": "string"
      },
      "description": "Component of the instance."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Preview Api V1 Clusters  Cluster Id  Services  Service  Config Preview Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Preview the files of a component instance",
    "tags": [
     "configs"
    ],
    "description": "Renders the configuration files one instance would receive with the current version and its groups: `path`, `mode`, `owner`, `group`, `content`, secrets redacted. Nothing is written. Permission `configs:read`; `404 host_component_not_found`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/config/versions": {
   "get": {
    "operationId": "list_versions_api_v1_clusters__cluster_id__services__service__config_versions_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "query",
      "name": "limit",
      "required": false,
      "schema": {
       "default": 50,
       "maximum": 500,
       "minimum": 1,
       "title": "Limit",
       "type": "integer"
      },
      "description": "Maximum number of versions in the page, from 1 to 500. Default 50."
     },
     {
      "in": "query",
      "name": "cursor",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "minimum": 1,
         "type": "integer"
        },
        {
         "type": "null"
        }
       ],
       "title": "Cursor"
      },
      "description": "The `next_cursor` of the previous page: versions below this number are returned."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Versions Api V1 Clusters  Cluster Id  Services  Service  Config Versions Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the configuration versions",
    "tags": [
     "configs"
    ],
    "description": "Versions of the configuration, newest first: `version`, `note`, `restored_from`, `secret_keys`, `created_by`, `created_at`. Paginated with `limit` and `cursor`. Permission `configs:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/config/versions/{version}": {
   "get": {
    "operationId": "get_version_api_v1_clusters__cluster_id__services__service__config_versions__version__get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "path",
      "name": "version",
      "required": true,
      "schema": {
       "title": "Version",
       "type": "integer"
      },
      "description": "Version number, starting at 1."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Version Api V1 Clusters  Cluster Id  Services  Service  Config Versions  Version  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a configuration version",
    "tags": [
     "configs"
    ],
    "description": "Returns the values of one version (secrets masked) with its note and author. Permission `configs:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/config/versions/{version}/restore": {
   "post": {
    "operationId": "restore_api_v1_clusters__cluster_id__services__service__config_versions__version__restore_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "path",
      "name": "version",
      "required": true,
      "schema": {
       "title": "Version",
       "type": "integer"
      },
      "description": "Version number to restore."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Restore Api V1 Clusters  Cluster Id  Services  Service  Config Versions  Version  Restore Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Restore a configuration version",
    "tags": [
     "configs"
    ],
    "description": "Saves the values of an old version as a new version (note `restore of version N`) and returns `version` and `stale_hosts`; apply it to reach the hosts. Permission `configs:edit`. Audited as `config.restore`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/connection": {
   "delete": {
    "description": "Forgets a connected service and its sealed credentials; the service itself is left untouched. Permission `services:install`. Errors: `409 service_not_connected`, `409 service_in_use` while a consumer is bound to it. Audited as `service.disconnect`.",
    "operationId": "disconnect_service_api_v1_clusters__cluster_id__services__service__connection_delete",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Disconnect Service Api V1 Clusters  Cluster Id  Services  Service  Connection Delete",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Disconnect a connected service",
    "tags": [
     "services"
    ]
   },
   "patch": {
    "description": "Changes the address, the credentials (rotation) or the TLS settings of a connected service; a value left out keeps the stored one. With `dry_run` the change is checked like a connect validation and not saved. Credentials the service refuses are never saved (`422 connect_invalid`). Permission `services:install`; `409 service_not_connected`. Audited as `service.connection.update` (field names only, never values).",
    "operationId": "update_connection_api_v1_clusters__cluster_id__services__service__connection_patch",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__services__ConnectionPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the connection to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Update Connection Api V1 Clusters  Cluster Id  Services  Service  Connection Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update a connected service",
    "tags": [
     "services"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/connection/check": {
   "post": {
    "description": "Runs the health check and the authenticated check of a connected service and records the result in its monitoring history. Returns `service`, `health` and `health_details`. Permission `services:operate`; `409 service_not_connected`.",
    "operationId": "check_connection_api_v1_clusters__cluster_id__services__service__connection_check_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Check Connection Api V1 Clusters  Cluster Id  Services  Service  Connection Check Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Check a connected service now",
    "tags": [
     "services"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/dashboard": {
   "get": {
    "description": "Monitoring dashboard of a service over [`from`, `to`] (default: the last hour): instances, health and latest checks, availability over the period, metrics of its hosts, alerts, operations, configuration and, for a connected service, its connection. Permission `cluster:read`.",
    "operationId": "service_dashboard_view_api_v1_clusters__cluster_id__services__service__dashboard_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     },
     {
      "in": "query",
      "name": "from",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "From"
      },
      "description": "Start of the window, ISO 8601. Default: one hour before `to`."
     },
     {
      "in": "query",
      "name": "to",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "To"
      },
      "description": "End of the window, ISO 8601. Default: now."
     },
     {
      "in": "query",
      "name": "step",
      "required": false,
      "schema": {
       "default": 60,
       "maximum": 86400,
       "minimum": 10,
       "title": "Step",
       "type": "integer"
      },
      "description": "Width of a metric bucket in seconds, 10 to 86400. Default 60."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Service Dashboard View Api V1 Clusters  Cluster Id  Services  Service  Dashboard Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the monitoring dashboard of a service",
    "tags": [
     "services"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/logs": {
   "post": {
    "operationId": "service_logs_api_v1_clusters__cluster_id__services__service__logs_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LogsBody"
       }
      }
     },
     "required": true,
     "description": "Host, component and number of lines."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Service Logs Api V1 Clusters  Cluster Id  Services  Service  Logs Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Fetch the logs of a component instance",
    "tags": [
     "services"
    ],
    "description": "Starts an operation where the agent of the host reads the last lines of the component logs. Returns `operation_id` and `task_id`: read the lines with `GET /operations/{operation_id}/tasks/{task_id}/logs`. Permission `services:operate`. Audited as `service.logs`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/mode": {
   "get": {
    "operationId": "get_mode_api_v1_clusters__cluster_id__services__service__mode_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Mode Api V1 Clusters  Cluster Id  Services  Service  Mode Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the administrative state of a service",
    "tags": [
     "services"
    ],
    "description": "Returns the administrative state (`enabled`, `disabled`, `maintenance`, `quarantined`, `suspended`), its reason, whether the service may run (`run_authorized`) the security lock of the cluster and `modes`, the documented effect of every mode. Permission `cluster:read`."
   },
   "post": {
    "operationId": "set_mode_api_v1_clusters__cluster_id__services__service__mode_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ModeBody"
       }
      }
     },
     "required": true,
     "description": "Mode, reason and drain timeout."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Set Mode Api V1 Clusters  Cluster Id  Services  Service  Mode Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Apply an operating mode to a service",
    "tags": [
     "services"
    ],
    "description": "Applies one mode and returns the administrative state left behind, its documented `effect` on new requests and\ntransactions in flight, the `operation_id` when the mode stops processes, and the informative `ha` impact:\n\n- `drain`: new requests refused, transactions completed up to `drain_timeout_s` (default 300), processes\n  stopped, state `maintenance`;\n- `scale_to_zero`: processes stopped until a start, state `enabled`;\n- `security_suspend`: transactions aborted at once, processes stopped, state `suspended` (run authorisation\n  revoked); needs `pki:manage`;\n- `emergency_stop`: every component stopped at once, state `disabled`;\n- `disable`: no process change, state `disabled` (what would run it is refused);\n- `quarantine`: processes frozen, every change refused except a stop;\n- `maintenance`: state `maintenance`, nothing stopped;\n- `enable`: lifts the state, never starts anything; lifting a suspension needs `pki:manage` and a `reason`.\n\nPermission `services:operate`. Errors: `422 service_mode_reason_required`, `409 service_unmanaged`,\n`409 approval_required`. Audited as `service.mode.<mode>`."
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/sheet": {
   "get": {
    "description": "Every tab of the uniform component sheet from the observed state: `overview`, `instances`, `config`, `dependencies`, `logs`, `metrics`, `security` (TLS, endpoints, secrets set or not, ports, certificates, run users, profile), `operations`, `upgrade`, `backups`, `audit` and `support`. Permission `cluster:read`.",
    "operationId": "component_sheet_api_v1_clusters__cluster_id__services__service__sheet_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Component Sheet Api V1 Clusters  Cluster Id  Services  Service  Sheet Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the component sheet of a service",
    "tags": [
     "lifecycle"
    ]
   }
  },
  "/api/v1/clusters/{cluster_id}/services/{service}/upgrade": {
   "get": {
    "operationId": "upgrade_info_api_v1_clusters__cluster_id__services__service__upgrade_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Upgrade Info Api V1 Clusters  Cluster Id  Services  Service  Upgrade Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Check whether a service can be upgraded",
    "tags": [
     "lifecycle"
    ],
    "description": "Returns `from` (installed release), `to` (catalog release), `allowed` with the `problems`, `stateful`, `backup_before`, the `migrations`, whether a `rollback` is possible, the upgrade matrix and the `history` of the last 50 upgrades. Permission `cluster:read`."
   },
   "post": {
    "operationId": "start_upgrade_api_v1_clusters__cluster_id__services__service__upgrade_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "service",
      "required": true,
      "schema": {
       "title": "Service",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql` or `keycloak`."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpgradeBody"
       }
      }
     },
     "required": true,
     "description": "Canary host and optional approval."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Start Upgrade Api V1 Clusters  Cluster Id  Services  Service  Upgrade Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Upgrade a service",
    "tags": [
     "lifecycle"
    ],
    "description": "Upgrades the service to the catalog release in one operation:\n\n1. compatibility and preflight;\n2. backup of a stateful service;\n3. the canary host: fetch, stop, migration hooks, new files and units, start, health checks, smoke test;\n4. the other hosts one at a time, then the service check and the smoke test, and the new version recorded.\n\nThe tasks that bring the previous release back are sealed before anything runs. Returns `operation_id` and\n`upgrade_id`. Permission `services:install`; an approval under `banking-secure`. Audited as `service.upgrade`."
   }
  },
  "/api/v1/clusters/{cluster_id}/ssh-policy": {
   "get": {
    "operationId": "get_ssh_policy_api_v1_clusters__cluster_id__ssh_policy_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Ssh Policy Api V1 Clusters  Cluster Id  Ssh Policy Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the SSH policy of a cluster",
    "tags": [
     "node-security"
    ],
    "description": "Returns `allow_rsa`, `rsa_min_bits`, `approved_user_cas`, `bootstrap_user`, `spiffe_trust_domain` and `rotate_before_days`. Permission `cluster:read`; `404 cluster_not_found`."
   },
   "put": {
    "operationId": "put_ssh_policy_api_v1_clusters__cluster_id__ssh_policy_put",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SshPolicyIn"
       }
      }
     },
     "required": true,
     "description": "The SSH policy."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Put Ssh Policy Api V1 Clusters  Cluster Id  Ssh Policy Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Set the SSH policy of a cluster",
    "tags": [
     "node-security"
    ],
    "description": "Replaces the SSH policy and returns it. The bootstrap user and every approved CA key are checked first. Permission `hosts:manage`. Errors: `422 ssh_policy_refused` (weak or invalid key, refused user), `404 cluster_not_found`. Audited as `cluster.ssh_policy`."
   }
  },
  "/api/v1/clusters/{cluster_id}/summary": {
   "get": {
    "operationId": "summary_api_v1_clusters__cluster_id__summary_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Summary Api V1 Clusters  Cluster Id  Summary Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the summary of a cluster",
    "tags": [
     "clusters"
    ],
    "description": "Counters for the home page of a cluster: hosts by state, services by state and by health, open alerts (`critical`, `warning`) and running operations. Permission `cluster:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/support-bundles": {
   "get": {
    "operationId": "list_bundles_api_v1_clusters__cluster_id__support_bundles_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response List Bundles Api V1 Clusters  Cluster Id  Support Bundles Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the support bundles of a cluster",
    "tags": [
     "lifecycle"
    ],
    "description": "The last 50 bundles with their status, size, SHA-256, contents, redactions and operation. Permission `cluster:manage`."
   },
   "post": {
    "operationId": "create_bundle_api_v1_clusters__cluster_id__support_bundles_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Bundle Api V1 Clusters  Cluster Id  Support Bundles Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Build a support bundle",
    "tags": [
     "lifecycle"
    ],
    "description": "Starts an operation that collects log tails, the profile, the hosts, the service versions and states, the rendered configuration, the open alerts, the drift findings and the operation history into a tar.gz archive in which every secret and personal datum is masked. Returns `operation_id` and `bundle_id`. Permission `cluster:manage`. Audited as `support.bundle`."
   }
  },
  "/api/v1/clusters/{cluster_id}/support-bundles/{bundle_id}/download": {
   "get": {
    "operationId": "download_bundle_api_v1_clusters__cluster_id__support_bundles__bundle_id__download_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "bundle_id",
      "required": true,
      "schema": {
       "title": "Bundle Id",
       "type": "string"
      },
      "description": "Identifier of the support bundle."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {}
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Download a support bundle",
    "tags": [
     "lifecycle"
    ],
    "description": "Returns the `navin-support-<time>.tar.gz` archive of a succeeded bundle. Permission `cluster:manage`; `404 bundle_not_found`. Audited as `support.bundle_download`."
   }
  },
  "/api/v1/clusters/{cluster_id}/topology": {
   "get": {
    "operationId": "topology_api_v1_clusters__cluster_id__topology_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Topology Api V1 Clusters  Cluster Id  Topology Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the topology of a cluster",
    "tags": [
     "clusters"
    ],
    "description": "Hosts (`id`, `hostname`, `state`, `rack`) and component instances (`service`, `component`, `host_id`, `state`, `health`) of the cluster, to draw where every component runs. Permission `cluster:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/upgrades": {
   "get": {
    "operationId": "list_upgrades_api_v1_clusters__cluster_id__upgrades_get",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response List Upgrades Api V1 Clusters  Cluster Id  Upgrades Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the upgrades of a cluster",
    "tags": [
     "lifecycle"
    ],
    "description": "The last 200 upgrades of every service with their versions, status, backup and operations. Permission `cluster:read`."
   }
  },
  "/api/v1/clusters/{cluster_id}/upgrades/{upgrade_id}/restore": {
   "post": {
    "operationId": "restore_upgrade_api_v1_clusters__cluster_id__upgrades__upgrade_id__restore_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "upgrade_id",
      "required": true,
      "schema": {
       "title": "Upgrade Id",
       "type": "string"
      },
      "description": "Identifier of the upgrade."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ApprovalOnly"
       }
      }
     },
     "required": true,
     "description": "Optional approval."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Restore Upgrade Api V1 Clusters  Cluster Id  Upgrades  Upgrade Id  Restore Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Restore the backup taken before an upgrade",
    "tags": [
     "lifecycle"
    ],
    "description": "Starts the operation that brings back the previous release and its data from the backup taken before the upgrade, when a rollback is not possible. Returns `operation_id`. Permission `services:install`; `404 upgrade_not_found`; an approval under `banking-secure`. Audited as `service.restore`."
   }
  },
  "/api/v1/clusters/{cluster_id}/upgrades/{upgrade_id}/rollback": {
   "post": {
    "operationId": "rollback_api_v1_clusters__cluster_id__upgrades__upgrade_id__rollback_post",
    "parameters": [
     {
      "in": "path",
      "name": "cluster_id",
      "required": true,
      "schema": {
       "title": "Cluster Id",
       "type": "string"
      },
      "description": "Identifier of the cluster (an environment of hosts or a Kubernetes cluster managed by the Navin Manager)."
     },
     {
      "in": "path",
      "name": "upgrade_id",
      "required": true,
      "schema": {
       "title": "Upgrade Id",
       "type": "string"
      },
      "description": "Identifier of the upgrade."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ApprovalOnly"
       }
      }
     },
     "required": true,
     "description": "Optional approval."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Rollback Api V1 Clusters  Cluster Id  Upgrades  Upgrade Id  Rollback Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Roll an upgrade back",
    "tags": [
     "lifecycle"
    ],
    "description": "Starts the operation that replays the sealed tasks of the previous release and restores the previous configuration version. Refused when the descriptor declares it impossible or an irreversible migration ran (use the restore instead). Returns `operation_id`. Permission `services:install`; `404 upgrade_not_found`. Audited as `service.rollback`."
   }
  },
  "/api/v1/connections": {
   "get": {
    "operationId": "list_connections_api_v1_connections_get",
    "parameters": [
     {
      "in": "query",
      "name": "limit",
      "required": false,
      "schema": {
       "default": 50,
       "maximum": 500,
       "minimum": 1,
       "title": "Limit",
       "type": "integer"
      },
      "description": "Maximum number of connections in the page, from 1 to 500. Default 50."
     },
     {
      "in": "query",
      "name": "cursor",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 200,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Cursor"
      },
      "description": "The `next_cursor` of the previous page (the last name, lower case). Omit it for the first page."
     },
     {
      "in": "query",
      "name": "type",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "pattern": "^(clickhouse|elasticsearch|http|kafka|ldap|mysql|nats|oidc|opensearch|postgresql|qdrant|redis|s3|smtp|syslog)$",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Type"
      },
      "description": "Only the connections of this type, for example `postgresql`, `s3` or `kafka`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Connections Api V1 Connections Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the external connections",
    "tags": [
     "connections"
    ],
    "description": "Connections sorted by name: `id`, `name`, `type`, `params`, `secret` (set or not), `description`, `last_test`, `created_at`, `updated_at`. Paginated with `limit` and `cursor`. Permission `connections:read`."
   },
   "post": {
    "operationId": "create_connection_api_v1_connections_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ConnectionCreate"
       }
      }
     },
     "required": true,
     "description": "Name, type, parameters and secret of the connection."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Connection Api V1 Connections Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create a connection",
    "tags": [
     "connections"
    ],
    "description": "Saves a connection and returns it (`201`). Permission `connections:manage`. Errors: `409 connection_name_taken`, `422 connection_params_invalid` (fields in `details.fields`). Audited as `connection.create`."
   }
  },
  "/api/v1/connections/validate": {
   "post": {
    "description": "Dry run: checks the parameters of the type, then runs the real protocol test with the given secret. Returns the test result (`ok`, `error_code`, `latency_ms`...). Nothing is stored; the secret is never sent back nor audited. Permission `connections:manage`. Audited as `connection.validate`.",
    "operationId": "validate_connection_api_v1_connections_validate_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ConnectionValidate"
       }
      }
     },
     "required": true,
     "description": "Type, parameters and secret to test."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Validate Connection Api V1 Connections Validate Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Test a connection before saving it",
    "tags": [
     "connections"
    ]
   }
  },
  "/api/v1/connections/{connection_id}": {
   "delete": {
    "operationId": "delete_connection_api_v1_connections__connection_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "connection_id",
      "required": true,
      "schema": {
       "title": "Connection Id",
       "type": "string"
      },
      "description": "Identifier of the connection."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete a connection",
    "tags": [
     "connections"
    ],
    "description": "Deletes a connection no service is bound to. Answers `204`. Permission `connections:manage`. Errors: `404 connection_not_found`, `409 connection_in_use` (services in `details.services`). Audited as `connection.delete`."
   },
   "get": {
    "operationId": "get_connection_api_v1_connections__connection_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "connection_id",
      "required": true,
      "schema": {
       "title": "Connection Id",
       "type": "string"
      },
      "description": "Identifier of the connection."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Connection Api V1 Connections  Connection Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a connection",
    "tags": [
     "connections"
    ],
    "description": "Returns one connection, its secret masked. Permission `connections:read`; `404 connection_not_found`."
   },
   "patch": {
    "operationId": "patch_connection_api_v1_connections__connection_id__patch",
    "parameters": [
     {
      "in": "path",
      "name": "connection_id",
      "required": true,
      "schema": {
       "title": "Connection Id",
       "type": "string"
      },
      "description": "Identifier of the connection."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__connections__ConnectionPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the connection to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Patch Connection Api V1 Connections  Connection Id  Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update a connection",
    "tags": [
     "connections"
    ],
    "description": "Changes the fields given; the type cannot change. Returns the connection. Permission `connections:manage`. Errors: `404 connection_not_found`, `409 connection_name_taken`, `422 connection_params_invalid`. Audited as `connection.update`."
   }
  },
  "/api/v1/connections/{connection_id}/test": {
   "post": {
    "operationId": "test_connection_api_v1_connections__connection_id__test_post",
    "parameters": [
     {
      "in": "path",
      "name": "connection_id",
      "required": true,
      "schema": {
       "title": "Connection Id",
       "type": "string"
      },
      "description": "Identifier of the connection."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Test Connection Api V1 Connections  Connection Id  Test Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Test a saved connection",
    "tags": [
     "connections"
    ],
    "description": "Runs the protocol test with the stored parameters and secret, stores the result with its time in `last_test` and returns it (`ok`, `error_code`, `latency_ms`...). Permission `connections:manage`; `404 connection_not_found`. Audited as `connection.test`."
   }
  },
  "/api/v1/dr-exercises": {
   "get": {
    "operationId": "list_exercises_api_v1_dr_exercises_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Exercises Api V1 Dr Exercises Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the DR exercises and failovers",
    "tags": [
     "backup"
    ],
    "description": "The last 200 exercises and failover requests with their report: status, requester, approver, observed RPO and RTO compared with the targets, evidence. Permission `backup:read`."
   },
   "post": {
    "operationId": "request_exercise_api_v1_dr_exercises_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ExerciseIn"
       }
      }
     },
     "required": true,
     "description": "The DR plan."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Request Exercise Api V1 Dr Exercises Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Request a DR exercise",
    "tags": [
     "backup"
    ],
    "description": "Records an exercise request for a plan (`201`); another person must approve it before it can be completed. Permission `dr:manage`; `404 dr_plan_not_found`. Audited as `dr.exercise.request`."
   }
  },
  "/api/v1/dr-exercises/{exercise_id}/approve": {
   "post": {
    "operationId": "approve_exercise_api_v1_dr_exercises__exercise_id__approve_post",
    "parameters": [
     {
      "in": "path",
      "name": "exercise_id",
      "required": true,
      "schema": {
       "title": "Exercise Id",
       "type": "string"
      },
      "description": "Identifier of the exercise or failover request."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Approve Exercise Api V1 Dr Exercises  Exercise Id  Approve Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Approve a DR exercise or failover",
    "tags": [
     "backup"
    ],
    "description": "Approves the request; the approver must not be the requester. Permission `dr:manage`. Errors: `403 restore_self_approval`, `404 dr_exercise_not_found`. Audited as `dr.approve`."
   }
  },
  "/api/v1/dr-exercises/{exercise_id}/complete": {
   "post": {
    "operationId": "complete_exercise_api_v1_dr_exercises__exercise_id__complete_post",
    "parameters": [
     {
      "in": "path",
      "name": "exercise_id",
      "required": true,
      "schema": {
       "title": "Exercise Id",
       "type": "string"
      },
      "description": "Identifier of the exercise or failover request."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CompleteIn"
       }
      }
     },
     "required": true,
     "description": "Observed measures, result and evidence."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Complete Exercise Api V1 Dr Exercises  Exercise Id  Complete Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Complete a DR exercise with its measures",
    "tags": [
     "backup"
    ],
    "description": "Records the observed RPO and RTO, the result and the evidence of an approved exercise or failover. Permission `dr:manage`; `409 dr_not_approved`. Audited as `dr.complete`."
   }
  },
  "/api/v1/dr-failovers/request": {
   "post": {
    "operationId": "request_failover_api_v1_dr_failovers_request_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ExerciseIn"
       }
      }
     },
     "required": true,
     "description": "The DR plan."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Request Failover Api V1 Dr Failovers Request Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Request a DR failover",
    "tags": [
     "backup"
    ],
    "description": "Records a real failover request for a plan (`201`); it follows the same approval and completion as an exercise. Permission `dr:manage`; `404 dr_plan_not_found`. Audited as `dr.failover.request`."
   }
  },
  "/api/v1/dr-plans": {
   "get": {
    "operationId": "list_dr_plans_api_v1_dr_plans_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Dr Plans Api V1 Dr Plans Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the DR plans",
    "tags": [
     "backup"
    ],
    "description": "Every disaster recovery plan with its mode, its primary and secondary sites, its RPO and RTO targets and its sequence. Permission `backup:read`."
   },
   "post": {
    "operationId": "create_dr_plan_api_v1_dr_plans_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DrPlanIn"
       }
      }
     },
     "required": true,
     "description": "Name, mode, sites, targets and sequence of the plan."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Dr Plan Api V1 Dr Plans Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create a DR plan",
    "tags": [
     "backup"
    ],
    "description": "Creates a plan between a primary and a secondary site (created when unknown) and returns it (`201`). Permission `dr:manage`. Errors: `422 dr_mode_invalid`, `422 dr_same_site`. Audited as `dr.plan.create`."
   }
  },
  "/api/v1/dr-plans/{plan_id}/switch-plan": {
   "post": {
    "operationId": "traffic_switch_plan_api_v1_dr_plans__plan_id__switch_plan_post",
    "parameters": [
     {
      "in": "path",
      "name": "plan_id",
      "required": true,
      "schema": {
       "title": "Plan Id",
       "type": "string"
      },
      "description": "Identifier of the DR plan."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SwitchIn"
       }
      }
     },
     "required": true,
     "description": "Site to switch the traffic to."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Traffic Switch Plan Api V1 Dr Plans  Plan Id  Switch Plan Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Plan a traffic switch to a site",
    "tags": [
     "backup"
    ],
    "description": "Runs the health checks of the declared switches against the target site (real HTTP requests) and returns the ordered DNS and load balancer changes. Nothing is applied: applying needs the API of your DNS and load balancer (status `requires_client_provider`). Permission `dr:manage`."
   }
  },
  "/api/v1/dr-plans/{plan_id}/targets": {
   "put": {
    "operationId": "set_dr_targets_api_v1_dr_plans__plan_id__targets_put",
    "parameters": [
     {
      "in": "path",
      "name": "plan_id",
      "required": true,
      "schema": {
       "title": "Plan Id",
       "type": "string"
      },
      "description": "Identifier of the DR plan."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TargetsIn"
       }
      }
     },
     "required": true,
     "description": "RPO and RTO targets."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Set Dr Targets Api V1 Dr Plans  Plan Id  Targets Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Set the RPO and RTO targets of a DR plan",
    "tags": [
     "backup"
    ],
    "description": "Sets your own recovery objectives (seconds, or null to clear); the product never proposes them. Permission `dr:manage`; `404 dr_plan_not_found`. Audited as `dr.plan.targets`."
   }
  },
  "/api/v1/dr-plans/{plan_id}/traffic": {
   "get": {
    "operationId": "list_traffic_api_v1_dr_plans__plan_id__traffic_get",
    "parameters": [
     {
      "in": "path",
      "name": "plan_id",
      "required": true,
      "schema": {
       "title": "Plan Id",
       "type": "string"
      },
      "description": "Identifier of the DR plan."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Traffic Api V1 Dr Plans  Plan Id  Traffic Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the traffic switches of a DR plan",
    "tags": [
     "backup"
    ],
    "description": "DNS records and load balancers declared for the plan, with their value per site and health check. Permission `backup:read`."
   },
   "post": {
    "operationId": "declare_traffic_api_v1_dr_plans__plan_id__traffic_post",
    "parameters": [
     {
      "in": "path",
      "name": "plan_id",
      "required": true,
      "schema": {
       "title": "Plan Id",
       "type": "string"
      },
      "description": "Identifier of the DR plan."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TrafficIn"
       }
      }
     },
     "required": true,
     "description": "Kind, name and specification of the switch."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Declare Traffic Api V1 Dr Plans  Plan Id  Traffic Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Declare a traffic switch of a DR plan",
    "tags": [
     "backup"
    ],
    "description": "Declares (or replaces) a DNS record or a load balancer of the plan with its value per site and the health check that must pass before a switch (`201`). Permission `dr:manage`. Errors: `422 dr_traffic_invalid`, `404 dr_plan_not_found`. Audited as `dr.traffic.declare`."
   }
  },
  "/api/v1/dr-sites": {
   "get": {
    "operationId": "list_sites_api_v1_dr_sites_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Sites Api V1 Dr Sites Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the DR sites",
    "tags": [
     "backup"
    ],
    "description": "Sites known to the disaster recovery plans, with their role (`primary` or `secondary`). Sites are created by the plans. Permission `backup:read`."
   }
  },
  "/api/v1/ha-groups": {
   "get": {
    "operationId": "list_groups_api_v1_ha_groups_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Groups Api V1 Ha Groups Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the high availability groups",
    "tags": [
     "availability"
    ],
    "description": "Groups of every cluster the caller may read (`cluster:read`), sorted by name, each with its members, its HA status and its last test run."
   },
   "post": {
    "operationId": "create_group_api_v1_ha_groups_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/GroupIn"
       }
      }
     },
     "required": true,
     "description": "The group, its policy and its members."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Group Api V1 Ha Groups Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create a high availability group",
    "tags": [
     "availability"
    ],
    "description": "Declares a group and its members and returns it (`201`). The profile must be met by `desired_replicas` and `fault_domains`, two members cannot share a host. Permission `cluster:manage` on the cluster. Errors: `422 ha_profile_unmet`, `422 ha_mode_unsupported`, `422 ha_members_same_host`, `404 cluster_not_found`, `404 host_not_found`. Audited as `ha_group.create`."
   }
  },
  "/api/v1/ha-groups/{group_id}": {
   "get": {
    "operationId": "get_group_api_v1_ha_groups__group_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "group_id",
      "required": true,
      "schema": {
       "title": "Group Id",
       "type": "string"
      },
      "description": "Identifier of the HA group."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Group Api V1 Ha Groups  Group Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a high availability group",
    "tags": [
     "availability"
    ],
    "description": "Returns the group with its members, its HA status and its last test run. Permission `cluster:read` on its cluster; `404 ha_group_not_found`."
   }
  },
  "/api/v1/ha-groups/{group_id}/operations": {
   "get": {
    "operationId": "operations_api_v1_ha_groups__group_id__operations_get",
    "parameters": [
     {
      "in": "path",
      "name": "group_id",
      "required": true,
      "schema": {
       "title": "Group Id",
       "type": "string"
      },
      "description": "Identifier of the HA group."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Operations Api V1 Ha Groups  Group Id  Operations Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the failover history of a group",
    "tags": [
     "availability"
    ],
    "description": "Returns `test_runs` (status, fencing token, observed RTO and RPO in seconds, evidence, times), `fencing_operations` (member, method, verified, token) and the last 200 `events`. Permission `cluster:read`."
   }
  },
  "/api/v1/ha-groups/{group_id}/test-failover": {
   "post": {
    "operationId": "test_failover_api_v1_ha_groups__group_id__test_failover_post",
    "parameters": [
     {
      "in": "path",
      "name": "group_id",
      "required": true,
      "schema": {
       "title": "Group Id",
       "type": "string"
      },
      "description": "Identifier of the HA group."
     }
    ],
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Test Failover Api V1 Ha Groups  Group Id  Test Failover Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run a failover test",
    "tags": [
     "availability"
    ],
    "description": "Takes the failover lease of the group, records a test run with a new fencing token and, when the group is bound to installed components, starts the failover. Answers `202` with `run_id`, `status`, `fencing_token`, `executed` and the started `operations`. Permission `services:operate`. Errors: `409 ha_operation_locked` (another failover holds the lease), `409 ha_client_managed_refused`. Audited as `ha_group.test_failover`."
   }
  },
  "/api/v1/ha-modes": {
   "get": {
    "operationId": "ha_modes_api_v1_ha_modes_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Ha Modes Api V1 Ha Modes Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the deployment modes and their support",
    "tags": [
     "availability"
    ],
    "description": "Every deployment mode with `supported`, `ha_possible` and the `reason` in both languages. Any signed in user."
   }
  },
  "/api/v1/hosts": {
   "get": {
    "operationId": "list_all_hosts_api_v1_hosts_get",
    "parameters": [
     {
      "in": "query",
      "name": "cluster_id",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Cluster Id"
      },
      "description": "Only the hosts of this cluster."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List All Hosts Api V1 Hosts Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the hosts of every cluster",
    "tags": [
     "node-security"
    ],
    "description": "Hosts of every cluster the caller may read (or of one cluster), sorted by FQDN, with their trust state, management mode, identity, metrics, inventory and platform."
   }
  },
  "/api/v1/hosts/bootstrap": {
   "post": {
    "operationId": "host_bootstrap_api_v1_hosts_bootstrap_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BootstrapIn"
       }
      }
     },
     "required": true,
     "description": "Target host, jump hosts, SSH account, private key or certificate."
    },
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Host Bootstrap Api V1 Hosts Bootstrap Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Bootstrap a node agent over SSH",
    "tags": [
     "node-security"
    ],
    "description": "Starts an operation that installs and registers the agent on one host:\n\n1. the agent binary of the mirror is verified (SHA-256 and Ed25519 signature) before any connection;\n2. the host keys come from the request only, with strict host key checking, through the jump hosts if any;\n3. a temporary Ed25519 key is added for the run and used by every later step;\n4. the steps stage, install binary, install unit, activate and register each do nothing when already done;\n5. a failing step rolls back what the run created; at the end the temporary key and the staging directory are\n   removed.\n\nWith `use_sudo` only the exact lines of the sudo allowlist run. Answers `202` with `operation_id` and the\n`plan`. Permission `hosts:manage`. Errors: `422 ssh_policy_refused`, `404 cluster_not_found`. Audited as\n`host.bootstrap`."
   }
  },
  "/api/v1/hosts/bootstrap/plan": {
   "post": {
    "operationId": "bootstrap_plan_api_v1_hosts_bootstrap_plan_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BootstrapIn"
       }
      }
     },
     "required": true,
     "description": "Same body as a bootstrap."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Bootstrap Plan Api V1 Hosts Bootstrap Plan Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Preview the bootstrap of a node agent",
    "tags": [
     "node-security"
    ],
    "description": "Checks the credential against the SSH policy and returns the plan without connecting: SSH user, target, jumps, credential verdict, the sudoers file and its validation, the allowlist, the systemd unit and the staging directory. Permission `hosts:manage`; `422 ssh_policy_refused`."
   }
  },
  "/api/v1/hosts/enroll": {
   "post": {
    "operationId": "host_enroll_api_v1_hosts_enroll_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__node_security__EnrollIn"
       }
      }
     },
     "required": true,
     "description": "Cluster, FQDN and key fingerprint of the host."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Host Enroll Api V1 Hosts Enroll Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Issue an enrollment token for one agent key",
    "tags": [
     "node-security"
    ],
    "description": "Issues a single use token for one host and one key: `host_fingerprint` is the SHA-256 (hex) of the public key of the agent (`nm-agent` prints it before enrolling). The token expires after at most 15 minutes and is consumed by the first enrollment that presents a CSR of that exact key. Returns `id`, `token`, `expires_at`, `ttl_s`, `host_fingerprint` and `agent_url` (`201`). Permission `hosts:manage`. Audited as `host.enroll_token`."
   }
  },
  "/api/v1/hosts/preflight": {
   "post": {
    "operationId": "host_preflight_api_v1_hosts_preflight_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PreflightIn"
       }
      }
     },
     "required": true,
     "description": "SSH access, expected identity, ports and disks to check."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Host Preflight Api V1 Hosts Preflight Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run the preflight of a host before its bootstrap",
    "tags": [
     "node-security"
    ],
    "description": "Reads the host over SSH and from the Manager (DNS forward and reverse, TCP reachability, required ports free, disks, operating system) and returns the checks graded `pass`, `warning` or `blocking`, the `blocking` and `warnings` counts, a reproducible `digest` and the credential verdict. Nothing is installed. Permission `hosts:manage`. Errors: `422 ssh_policy_refused`. Audited as `host.preflight`."
   }
  },
  "/api/v1/hosts/{host_id}": {
   "delete": {
    "operationId": "delete_host_api_v1_hosts__host_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete a host",
    "tags": [
     "hosts"
    ],
    "description": "Removes the host from the Manager and revokes its agent certificates, without contacting the agent (use decommission to clean the machine). Answers `204`. Permission `hosts:manage`. Errors: `404 host_not_found`, `409 host_has_components`. Audited as `host.delete`."
   },
   "get": {
    "operationId": "get_host_api_v1_hosts__host_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Host Api V1 Hosts  Host Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a host with its facts",
    "tags": [
     "hosts"
    ],
    "description": "Returns the host with the full facts reported by its agent. Permission `cluster:read` on its cluster; `404 host_not_found`."
   },
   "patch": {
    "operationId": "patch_host_api_v1_hosts__host_id__patch",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/HostPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the host to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Patch Host Api V1 Hosts  Host Id  Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update the rack, labels or maintenance of a host",
    "tags": [
     "hosts"
    ],
    "description": "Changes the fields given and returns the host. Turning maintenance on moves the host to the `maintenance` state, turning it off brings it back to `healthy`. Permission `hosts:manage`; `422 host_environment_unknown`. Audited as `host.update`."
   }
  },
  "/api/v1/hosts/{host_id}/actions": {
   "post": {
    "operationId": "host_action_api_v1_hosts__host_id__actions_post",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/HostBulkBody"
       }
      }
     },
     "required": true,
     "description": "Action and dry run."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Host Action Api V1 Hosts  Host Id  Actions Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run an action on every component of a host",
    "tags": [
     "services"
    ],
    "description": "Starts one operation that starts, stops or restarts every component placed on the host, or only the components whose configuration changed (`restart_stale`), service after service in dependency order. Instances in maintenance and services whose administrative state forbids the action are left out and listed in `skipped`; with `dry_run` nothing is created and `operation_id` is null. Permission `services:operate` on the cluster of the host. Errors: `404 host_not_found`, `409 bulk_nothing_to_do`, `409 approval_required` (under `banking-secure`, stop and restarts need an approval for the service `host:<host id>`). Audited as `host.<action>`."
   }
  },
  "/api/v1/hosts/{host_id}/agent-update": {
   "post": {
    "description": "Verifies the signed agent binary of the mirror, then issues a signed `agent.update` command with its digest and signature (idempotency key derived from the digest). Returns the command envelope (`201`). Permission `hosts:manage`. Errors: `422 agent_package_untrusted`, `409 host_not_trusted`, `409 host_client_managed`.",
    "operationId": "agent_update_api_v1_hosts__host_id__agent_update_post",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateIn"
       }
      }
     },
     "required": true,
     "description": "Validity of the command and health timeout of the new agent."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Agent Update Api V1 Hosts  Host Id  Agent Update Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update the agent of a host",
    "tags": [
     "node-security"
    ]
   }
  },
  "/api/v1/hosts/{host_id}/breakglass": {
   "get": {
    "operationId": "breakglass_list_api_v1_hosts__host_id__breakglass_get",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Breakglass List Api V1 Hosts  Host Id  Breakglass Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the break glass requests of a host",
    "tags": [
     "node-security"
    ],
    "description": "The last 50 break glass requests of the host with their status, approvers, validity and evidence. Permission `cluster:read`."
   },
   "post": {
    "operationId": "breakglass_request_api_v1_hosts__host_id__breakglass_post",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BreakGlassIn"
       }
      }
     },
     "required": true,
     "description": "Reason, public key, account and validity."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Breakglass Request Api V1 Hosts  Host Id  Breakglass Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Request an emergency SSH access",
    "tags": [
     "node-security"
    ],
    "description": "Records a break glass request for the host with the reason, the public key of the requester and the TTL; two other users must approve it. Returns the request (`201`). Permission `hosts:manage`. Errors: `422 breakglass_key_refused`, `409 host_not_trusted`, `409 host_client_managed`. Audited as `host.breakglass.request`."
   }
  },
  "/api/v1/hosts/{host_id}/commands": {
   "post": {
    "operationId": "issue_command_api_v1_hosts__host_id__commands_post",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__node_security__CommandIn"
       }
      }
     },
     "required": true,
     "description": "Operation, parameters, validity and idempotency key."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Issue Command Api V1 Hosts  Host Id  Commands Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Send a signed command to an agent",
    "tags": [
     "node-security"
    ],
    "description": "Issues a command envelope signed with the Ed25519 key of the Manager for the agent of the host (the same idempotency key returns the stored envelope). Allowed operations: `facts.collect`, `health.check`, `logs.tail`, `files.digest`, `service.control`, `command.run`, `agent.update`; the last three are refused on client managed hosts. Returns the envelope (`201`). Permission `hosts:manage`. Errors: `422 command_operation_unknown`, `409 host_not_trusted`, `409 host_client_managed`. Audited as `host.command.issue`."
   }
  },
  "/api/v1/hosts/{host_id}/components": {
   "get": {
    "operationId": "host_components_api_v1_hosts__host_id__components_get",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Host Components Api V1 Hosts  Host Id  Components Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the components of a host",
    "tags": [
     "hosts"
    ],
    "description": "Component instances placed on the host: `service`, `component`, `desired_state`, `state`, `health` and its details, `version`, `config_version`, `stale_config` (the configuration changed since the last restart), `maintenance`, `pid`, `since`, `updated_at`. Permission `cluster:read`."
   }
  },
  "/api/v1/hosts/{host_id}/decommission": {
   "post": {
    "operationId": "decommission_api_v1_hosts__host_id__decommission_post",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Decommission Api V1 Hosts  Host Id  Decommission Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Decommission a host",
    "tags": [
     "hosts"
    ],
    "description": "Starts an operation in two stages: the agent runs its decommission task, then the Manager marks the host `decommissioned` and revokes its certificates. The host must have no component left. Answers `202` with `operation_id`. Permission `hosts:manage`; `409 host_has_components`. Audited as `host.decommission`."
   }
  },
  "/api/v1/hosts/{host_id}/facts/refresh": {
   "post": {
    "operationId": "refresh_facts_api_v1_hosts__host_id__facts_refresh_post",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Refresh Facts Api V1 Hosts  Host Id  Facts Refresh Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Collect the facts of a host again",
    "tags": [
     "hosts"
    ],
    "description": "Starts an operation where the agent collects and reports its facts again (the preflight checks are evaluated on them). Answers `202` with `operation_id`. Permission `hosts:manage`. Audited as `host.facts_refresh`."
   }
  },
  "/api/v1/hosts/{host_id}/inventory": {
   "get": {
    "operationId": "host_inventory_api_v1_hosts__host_id__inventory_get",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Host Inventory Api V1 Hosts  Host Id  Inventory Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the inventory of a host",
    "tags": [
     "node-security"
    ],
    "description": "Returns `host_id`, the `inventory` reconciled from the agent facts (hardware, GPUs, platform) and `updated_at`. Permission `cluster:read`."
   }
  },
  "/api/v1/hosts/{host_id}/management": {
   "put": {
    "operationId": "set_management_api_v1_hosts__host_id__management_put",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ManagementIn"
       }
      }
     },
     "required": true,
     "description": "The management mode."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Set Management Api V1 Hosts  Host Id  Management Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Set who manages a host",
    "tags": [
     "node-security"
    ],
    "description": "Sets the management mode: `platform` (the Manager acts on the host) or `client` (the dangerous commands and break glass are refused). Returns the node. Permission `hosts:manage`. Audited as `host.management`."
   }
  },
  "/api/v1/hosts/{host_id}/metrics": {
   "get": {
    "operationId": "host_metrics_api_v1_hosts__host_id__metrics_get",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     },
     {
      "in": "query",
      "name": "from",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "From"
      },
      "description": "Start of the window, ISO 8601. Default: one hour before `to`."
     },
     {
      "in": "query",
      "name": "to",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "To"
      },
      "description": "End of the window, ISO 8601. Default: now."
     },
     {
      "in": "query",
      "name": "step",
      "required": false,
      "schema": {
       "default": 60,
       "maximum": 86400,
       "minimum": 10,
       "title": "Step",
       "type": "integer"
      },
      "description": "Width of a bucket in seconds, 10 to 86400. Default 60."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Host Metrics Api V1 Hosts  Host Id  Metrics Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Read the metrics of a host",
    "tags": [
     "hosts"
    ],
    "description": "Time series of the host over [`from`, `to`] (default: the last hour) in buckets of `step` seconds: `cpu_pct`, `mem_used_mb`, `load1`, `disk_pct`, `net_rx`, `net_tx`, each a list of `[time, value]`. Permission `cluster:read`."
   }
  },
  "/api/v1/hosts/{host_id}/parameters": {
   "get": {
    "operationId": "get_parameters_api_v1_hosts__host_id__parameters_get",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Parameters Api V1 Hosts  Host Id  Parameters Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the kernel parameters of a host",
    "tags": [
     "hosts"
    ],
    "description": "The sysctl settings and the resource limits (`nofile`, `nproc`, `memlock`) of the host, each with its `current` value (reported by the agent), its `desired` value (set with PUT) and its `recommended` value (from the installed services), plus the firewall backend and the ports in use. Permission `cluster:read`."
   },
   "put": {
    "operationId": "put_parameters_api_v1_hosts__host_id__parameters_put",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ParametersIn"
       }
      }
     },
     "required": true,
     "description": "Sysctl settings and resource limits."
    },
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Put Parameters Api V1 Hosts  Host Id  Parameters Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Apply kernel parameters to a host",
    "tags": [
     "hosts"
    ],
    "description": "Stores the sysctl settings and resource limits and starts an operation that writes them to `/etc/sysctl.d/90-navin-manager.conf` and `/etc/security/limits.d/90-navin-manager.conf`. Answers `202` with `operation_id`. Permission `hosts:manage`. Errors: `422 validation_error` (invalid key or empty request), `409 host_rootless` (agent without root rights). Audited as `host.parameters`."
   }
  },
  "/api/v1/hosts/{host_id}/preflight": {
   "get": {
    "operationId": "preflight_results_api_v1_hosts__host_id__preflight_get",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response Preflight Results Api V1 Hosts  Host Id  Preflight Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the preflight results of a host",
    "tags": [
     "hosts"
    ],
    "description": "Result of every preflight check of the host (`check`, `status`, `message_i18n`, `details`, `checked_at`), evaluated from its last facts. Permission `cluster:read`."
   },
   "post": {
    "operationId": "run_preflight_api_v1_hosts__host_id__preflight_post",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Run Preflight Api V1 Hosts  Host Id  Preflight Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Run the preflight checks of a host",
    "tags": [
     "hosts"
    ],
    "description": "Starts an operation that collects fresh facts; the preflight checks are evaluated when they arrive. Read the results with `GET /hosts/{host_id}/preflight`. Answers `202` with `operation_id`. Permission `hosts:manage`. Audited as `host.preflight`."
   }
  },
  "/api/v1/hosts/{host_id}/quarantine": {
   "post": {
    "operationId": "quarantine_host_api_v1_hosts__host_id__quarantine_post",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TrustIn"
       }
      }
     },
     "required": true,
     "description": "Reason of the change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Quarantine Host Api V1 Hosts  Host Id  Quarantine Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Quarantine a host",
    "tags": [
     "node-security"
    ],
    "description": "Sets the trust state to `quarantined`: the Manager stops trusting the agent for new commands until it is recovered. Returns the node. Permission `hosts:manage`. Audited as `host.quarantine`."
   }
  },
  "/api/v1/hosts/{host_id}/receipts": {
   "get": {
    "operationId": "host_receipts_api_v1_hosts__host_id__receipts_get",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     },
     {
      "in": "query",
      "name": "limit",
      "required": false,
      "schema": {
       "default": 50,
       "maximum": 500,
       "minimum": 1,
       "title": "Limit",
       "type": "integer"
      },
      "description": "Maximum number of receipts, from 1 to 500. Default 50."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Host Receipts Api V1 Hosts  Host Id  Receipts Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the command receipts of a host",
    "tags": [
     "node-security"
    ],
    "description": "Receipts of the signed commands run by the agent, last completed first: operation, start and end, exit code, observed state, error code and evidence, redacted. Permission `cluster:read`."
   }
  },
  "/api/v1/hosts/{host_id}/recover": {
   "post": {
    "operationId": "recover_host_api_v1_hosts__host_id__recover_post",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TrustIn"
       }
      }
     },
     "required": true,
     "description": "Reason of the change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Recover Host Api V1 Hosts  Host Id  Recover Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Trust a quarantined host again",
    "tags": [
     "node-security"
    ],
    "description": "Sets the trust state back to `trusted`. A revoked host cannot be recovered: it must enroll again (`409 agent_revoked`). Returns the node. Permission `hosts:manage`. Audited as `host.recover`."
   }
  },
  "/api/v1/hosts/{host_id}/revoke": {
   "post": {
    "operationId": "revoke_host_api_v1_hosts__host_id__revoke_post",
    "parameters": [
     {
      "in": "path",
      "name": "host_id",
      "required": true,
      "schema": {
       "title": "Host Id",
       "type": "string"
      },
      "description": "Identifier of the host, a machine registered by its Navin agent."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TrustIn"
       }
      }
     },
     "required": true,
     "description": "Reason of the change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Revoke Host Api V1 Hosts  Host Id  Revoke Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Revoke the agent of a host",
    "tags": [
     "node-security"
    ],
    "description": "Sets the trust state to `revoked`, revokes the certificates of the agent and expires its pending commands. Only a new enrollment brings it back. Returns the node. Permission `hosts:manage`. Audited as `host.revoke` with the number of certificates revoked."
   }
  },
  "/api/v1/hub": {
   "get": {
    "operationId": "get_status_api_v1_hub_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Status Api V1 Hub Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the Hub status",
    "tags": [
     "hub"
    ],
    "description": "Returns `configured`, the public `settings` (the token is never returned), the `state` of the last accepted document and a `packages_summary`. Permission `system:read`."
   }
  },
  "/api/v1/hub/import": {
   "post": {
    "operationId": "import_offline_api_v1_hub_import_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "additionalProperties": true,
        "title": "Document",
        "type": "object"
       }
      }
     },
     "required": true,
     "description": "The signed distribution document, as JSON."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Import Offline Api V1 Hub Import Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Import a distribution document offline",
    "tags": [
     "hub"
    ],
    "description": "Verifies and stores a signed document brought on removable media (air-gapped site). Needs the customer and the pinned keys in the settings. Returns `metadata_version`, `targets`, `images_loaded` and `changes`. Permission `settings:manage`; `422 hub_document_invalid` when a check fails. Audited as `hub.import`."
   }
  },
  "/api/v1/hub/packages": {
   "get": {
    "operationId": "list_packages_api_v1_hub_packages_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Packages Api V1 Hub Packages Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the approved packages",
    "tags": [
     "hub"
    ],
    "description": "Targets of the accepted document (project, name, version, image, revocation), each with whether it is the latest approved version and whether it is installed on a cluster. Returns `items`. Permission `system:read`."
   }
  },
  "/api/v1/hub/settings": {
   "put": {
    "operationId": "put_settings_api_v1_hub_settings_put",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/HubSettingsBody"
       }
      }
     },
     "required": true,
     "description": "Hub address, customer, keys and token."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Put Settings Api V1 Hub Settings Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Save the Hub settings",
    "tags": [
     "hub"
    ],
    "description": "Saves the connection to the Hub and returns the status. The token is sealed; leave it null to keep the stored one. Permission `settings:manage`; `422 hub_document_invalid` when `trusted_keys_pem` holds no Ed25519 public key. Audited as `hub.settings` (key identifiers only)."
   }
  },
  "/api/v1/hub/sync": {
   "post": {
    "operationId": "sync_api_v1_hub_sync_post",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Sync Api V1 Hub Sync Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Sync with the Hub",
    "tags": [
     "hub"
    ],
    "description": "Downloads the document of the customer from the Hub, verifies and stores it. Needs the URL, the customer and the pinned keys in the settings. Returns `metadata_version`, `targets`, `images_loaded` and `changes`. Permission `settings:manage`. Audited as `hub.sync`."
   }
  },
  "/api/v1/mcp/hosted": {
   "get": {
    "description": "Hosted servers of a tenant (one project or all) with `url`, bearer `token`, `allowed_tools`, `status` and `hosted_at`, for the Navin Enterprise platform. Permission `mcp:publish` (admin role only). Audited as `mcp.hosted_list` (identifiers only, never a token).",
    "operationId": "hosted_servers_api_v1_mcp_hosted_get",
    "parameters": [
     {
      "description": "Tenant slug.",
      "in": "query",
      "name": "tenant",
      "required": true,
      "schema": {
       "description": "tenant slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Tenant",
       "type": "string"
      }
     },
     {
      "description": "Project slug; every project of the tenant when absent.",
      "in": "query",
      "name": "project",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "project slug (every project if absent)",
       "title": "Project"
      }
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Hosted Servers Api V1 Mcp Hosted Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the hosted MCP servers with their tokens",
    "tags": [
     "mcp"
    ]
   }
  },
  "/api/v1/mcp/hosting": {
   "get": {
    "description": "Per cluster: whether `mcp-host` is installed, its instances (FQDN, base URL, state) and the number of servers each one hosts. A server is placed on one instance by a hash of its identifier. Permission `mcp:read`.",
    "operationId": "hosting_infrastructure_api_v1_mcp_hosting_get",
    "parameters": [
     {
      "in": "query",
      "name": "cluster_id",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "pattern": "^[0-9a-fA-F-]{36}$",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Cluster Id"
      },
      "description": "Only this cluster (UUID)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Hosting Infrastructure Api V1 Mcp Hosting Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get the MCP hosting infrastructure",
    "tags": [
     "mcp"
    ]
   }
  },
  "/api/v1/mcp/presets": {
   "get": {
    "description": "Presets of the Navin library (name, category, transport, hosting, fields to fill), sorted by category and name. Permission `mcp:read`; `503 mcp_presets_unavailable`.",
    "operationId": "list_presets_api_v1_mcp_presets_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Presets Api V1 Mcp Presets Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the MCP presets",
    "tags": [
     "mcp"
    ]
   }
  },
  "/api/v1/mcp/servers": {
   "get": {
    "description": "Servers of one project of one tenant (both required), without any secret value. Permission `mcp:read`.",
    "operationId": "list_servers_api_v1_mcp_servers_get",
    "parameters": [
     {
      "description": "Tenant slug.",
      "in": "query",
      "name": "tenant",
      "required": true,
      "schema": {
       "description": "tenant slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Tenant",
       "type": "string"
      }
     },
     {
      "description": "Project slug.",
      "in": "query",
      "name": "project",
      "required": true,
      "schema": {
       "description": "project slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Project",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Servers Api V1 Mcp Servers Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the MCP servers of a project",
    "tags": [
     "mcp"
    ]
   },
   "post": {
    "operationId": "create_server_api_v1_mcp_servers_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ServerIn"
       }
      }
     },
     "required": true,
     "description": "Tenant, project and definition of the server."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Server Api V1 Mcp Servers Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create an MCP server",
    "tags": [
     "mcp"
    ],
    "description": "Creates a server from a preset (its required fields are mandatory) or a custom one, and returns it (`201`). A preset whose URL is not internal needs `url` set to the internal address of its server. Permission `mcp:manage`. Errors: `422 mcp_fields_missing`, `422 mcp_fields_unknown`, `422 mcp_target_required`, `422 mcp_online_forbidden`, `404 mcp_preset_not_found`, `409 mcp_server_name_taken`. Audited as `mcp.create`."
   }
  },
  "/api/v1/mcp/servers/{server_id}": {
   "delete": {
    "operationId": "delete_server_api_v1_mcp_servers__server_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "server_id",
      "required": true,
      "schema": {
       "title": "Server Id",
       "type": "string"
      },
      "description": "Identifier of the MCP server."
     },
     {
      "description": "Tenant slug of the server: lower case letters, digits and `-`, at most 63 characters.",
      "in": "query",
      "name": "tenant",
      "required": true,
      "schema": {
       "description": "tenant slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Tenant",
       "type": "string"
      }
     },
     {
      "description": "Project slug of the server.",
      "in": "query",
      "name": "project",
      "required": true,
      "schema": {
       "description": "project slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Project",
       "type": "string"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete an MCP server",
    "tags": [
     "mcp"
    ],
    "description": "Deletes the server; a hosted server is withdrawn from its hosting first. Answers `204`. Permission `mcp:manage`; `404 mcp_server_not_found`. Audited as `mcp.delete`."
   },
   "get": {
    "operationId": "get_server_api_v1_mcp_servers__server_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "server_id",
      "required": true,
      "schema": {
       "title": "Server Id",
       "type": "string"
      },
      "description": "Identifier of the MCP server."
     },
     {
      "description": "Tenant slug of the server.",
      "in": "query",
      "name": "tenant",
      "required": true,
      "schema": {
       "description": "tenant slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Tenant",
       "type": "string"
      }
     },
     {
      "description": "Project slug of the server.",
      "in": "query",
      "name": "project",
      "required": true,
      "schema": {
       "description": "project slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Project",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Server Api V1 Mcp Servers  Server Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get an MCP server",
    "tags": [
     "mcp"
    ],
    "description": "Returns the server with its transport, URL or command, allowed tools, configured and secret field names, last test and hosting (state, cluster, URL; never the token). Permission `mcp:read`; `404 mcp_server_not_found`."
   },
   "patch": {
    "operationId": "update_server_api_v1_mcp_servers__server_id__patch",
    "parameters": [
     {
      "in": "path",
      "name": "server_id",
      "required": true,
      "schema": {
       "title": "Server Id",
       "type": "string"
      },
      "description": "Identifier of the MCP server."
     },
     {
      "description": "Tenant slug of the server.",
      "in": "query",
      "name": "tenant",
      "required": true,
      "schema": {
       "description": "tenant slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Tenant",
       "type": "string"
      }
     },
     {
      "description": "Project slug of the server.",
      "in": "query",
      "name": "project",
      "required": true,
      "schema": {
       "description": "project slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Project",
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ServerPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the server to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Update Server Api V1 Mcp Servers  Server Id  Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update an MCP server",
    "tags": [
     "mcp"
    ],
    "description": "Changes the fields given and returns the server. `values` is merged with the stored ones; `url`, `command`, `args`, `headers` and `env` apply to custom servers only (`422 mcp_custom_only`). Disabling a hosted server withdraws it from its hosting. Permission `mcp:manage`. Errors: `422 mcp_fields_unknown`, `422 mcp_online_forbidden`. Audited as `mcp.update`."
   }
  },
  "/api/v1/mcp/servers/{server_id}/hosting": {
   "delete": {
    "description": "Takes the server out of its hosting: status `removing`, then the `mcp.hosting.apply` operation without it (`none` at the end). Answers `202` with the server and `operation_id`. Permission `mcp:manage`; `409 mcp_not_hosted`. Audited as `mcp.unhost`.",
    "operationId": "unhost_server_api_v1_mcp_servers__server_id__hosting_delete",
    "parameters": [
     {
      "in": "path",
      "name": "server_id",
      "required": true,
      "schema": {
       "title": "Server Id",
       "type": "string"
      },
      "description": "Identifier of the MCP server."
     },
     {
      "description": "Tenant slug of the server.",
      "in": "query",
      "name": "tenant",
      "required": true,
      "schema": {
       "description": "tenant slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Tenant",
       "type": "string"
      }
     },
     {
      "description": "Project slug of the server.",
      "in": "query",
      "name": "project",
      "required": true,
      "schema": {
       "description": "project slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Project",
       "type": "string"
      }
     }
    ],
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Unhost Server Api V1 Mcp Servers  Server Id  Hosting Delete",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Stop hosting an MCP server",
    "tags": [
     "mcp"
    ]
   },
   "post": {
    "description": "Hosts a stdio server on the `mcp-host` service of a cluster: a new bearer token (sealed; the runtime only receives its SHA-256), status `deploying`, then the `mcp.hosting.apply` operation that writes `servers.json` on every instance; the status becomes `hosted` or `failed`. Answers `202` with the server and `operation_id`. Permission `mcp:manage`. Errors: `422 mcp_hosting_stdio_only`, `409 mcp_hosting_disabled`, `409 mcp_host_not_installed`. Audited as `mcp.host`.",
    "operationId": "host_server_api_v1_mcp_servers__server_id__hosting_post",
    "parameters": [
     {
      "in": "path",
      "name": "server_id",
      "required": true,
      "schema": {
       "title": "Server Id",
       "type": "string"
      },
      "description": "Identifier of the MCP server."
     },
     {
      "description": "Tenant slug of the server.",
      "in": "query",
      "name": "tenant",
      "required": true,
      "schema": {
       "description": "tenant slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Tenant",
       "type": "string"
      }
     },
     {
      "description": "Project slug of the server.",
      "in": "query",
      "name": "project",
      "required": true,
      "schema": {
       "description": "project slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Project",
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/HostingIn"
       }
      }
     },
     "required": true,
     "description": "Cluster and limits of the hosting."
    },
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Host Server Api V1 Mcp Servers  Server Id  Hosting Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Host a stdio MCP server on a cluster",
    "tags": [
     "mcp"
    ]
   }
  },
  "/api/v1/mcp/servers/{server_id}/hosting/token": {
   "post": {
    "description": "Issues a new bearer token and applies it; the previous token stops working once applied. Answers `202`. Permission `mcp:manage`. Errors: `409 mcp_not_hosted`, `409 mcp_hosting_disabled`. Audited as `mcp.hosting_token`.",
    "operationId": "renew_token_api_v1_mcp_servers__server_id__hosting_token_post",
    "parameters": [
     {
      "in": "path",
      "name": "server_id",
      "required": true,
      "schema": {
       "title": "Server Id",
       "type": "string"
      },
      "description": "Identifier of the MCP server."
     },
     {
      "description": "Tenant slug of the server.",
      "in": "query",
      "name": "tenant",
      "required": true,
      "schema": {
       "description": "tenant slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Tenant",
       "type": "string"
      }
     },
     {
      "description": "Project slug of the server.",
      "in": "query",
      "name": "project",
      "required": true,
      "schema": {
       "description": "project slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Project",
       "type": "string"
      }
     }
    ],
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Renew Token Api V1 Mcp Servers  Server Id  Hosting Token Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Renew the token of a hosted MCP server",
    "tags": [
     "mcp"
    ]
   }
  },
  "/api/v1/mcp/servers/{server_id}/test": {
   "post": {
    "description": "Speaks MCP to the server (`initialize`, `notifications/initialized`, `tools/list`) over streamable HTTP, SSE, or stdin and stdout of the command when it is on the PATH (no shell, with a timeout); a hosted server is tested at its hosted URL with its token. Returns and keeps in `last_test` the result `{ok, tools, server_info, error, tested_at}`; an error never repeats a secret value. Permission `mcp:manage`; `422 mcp_online_forbidden`. Audited as `mcp.test`.",
    "operationId": "test_server_api_v1_mcp_servers__server_id__test_post",
    "parameters": [
     {
      "in": "path",
      "name": "server_id",
      "required": true,
      "schema": {
       "title": "Server Id",
       "type": "string"
      },
      "description": "Identifier of the MCP server."
     },
     {
      "description": "Tenant slug of the server.",
      "in": "query",
      "name": "tenant",
      "required": true,
      "schema": {
       "description": "tenant slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Tenant",
       "type": "string"
      }
     },
     {
      "description": "Project slug of the server.",
      "in": "query",
      "name": "project",
      "required": true,
      "schema": {
       "description": "project slug",
       "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
       "title": "Project",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Test Server Api V1 Mcp Servers  Server Id  Test Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Test an MCP server",
    "tags": [
     "mcp"
    ]
   }
  },
  "/api/v1/me": {
   "get": {
    "operationId": "me_api_v1_me_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Me Api V1 Me Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Read my profile",
    "tags": [
     "me"
    ],
    "description": "Returns the account of the caller: identifier, username, display name, email, source (`local`, `ldap`, `oidc`), role bindings, MFA state, language, lock and last sign in."
   },
   "patch": {
    "operationId": "patch_me_api_v1_me_patch",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MePatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the profile to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Patch Me Api V1 Me Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update my profile",
    "tags": [
     "me"
    ],
    "description": "Changes the display name, the email or the language of the caller; a field left out is kept. Browser session only. Returns the updated profile. Audited as `user.profile_update` with the names of the changed fields."
   }
  },
  "/api/v1/me/tokens": {
   "get": {
    "operationId": "list_tokens_api_v1_me_tokens_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Tokens Api V1 Me Tokens Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List my API tokens",
    "tags": [
     "me"
    ],
    "description": "Lists every token of the caller, newest first, revoked ones included: `id`, `name`, `prefix`, `permissions` (null: every permission of the user), `expires_at`, `last_used_at`, `revoked_at`, `created_at`. The secret is never returned."
   },
   "post": {
    "operationId": "create_token_api_v1_me_tokens_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TokenBody"
       }
      }
     },
     "required": true,
     "description": "Name, optional permission subset and lifetime of the token."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Token Api V1 Me Tokens Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create a personal API token",
    "tags": [
     "me"
    ],
    "description": "Creates a token and returns `token` (the full secret, shown only in this answer), `id`, `prefix`, `name`,\n`permissions` and `expires_at`. Answers `201`. Browser session only (`403 session_required` with a token).\nErrors: `422 permission_unknown` (a permission that does not exist), `403 token_permissions_exceed` (a\npermission you do not hold). Audited as `token.create`."
   }
  },
  "/api/v1/me/tokens/{token_id}": {
   "delete": {
    "operationId": "revoke_token_api_v1_me_tokens__token_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "token_id",
      "required": true,
      "schema": {
       "title": "Token Id",
       "type": "string"
      },
      "description": "Identifier of the API token, from `GET /me/tokens`."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Revoke one of my API tokens",
    "tags": [
     "me"
    ],
    "description": "Revokes the token at once (revoking it again is harmless). Browser session only. Answers `204`; `404 token_not_found` when the token is not one of yours. Audited as `token.revoke`."
   }
  },
  "/api/v1/mirror": {
   "get": {
    "operationId": "status_api_v1_mirror_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Status Api V1 Mirror Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the mirror status",
    "tags": [
     "mirror"
    ],
    "description": "Returns the mirror `url` and `registry`, `manifest_loaded`, `loaded_at`, the number of `artifacts`, `images` and `python` packages loaded, and `missing`, what the catalog needs that the mirror lacks. Permission `system:read`."
   }
  },
  "/api/v1/mirror/reload": {
   "post": {
    "operationId": "reload_api_v1_mirror_reload_post",
    "parameters": [
     {
      "in": "query",
      "name": "verify",
      "required": false,
      "schema": {
       "default": false,
       "title": "Verify",
       "type": "boolean"
      },
      "description": "Also check the SHA-256 digest of every file against the manifest (slower). Default false."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Reload Api V1 Mirror Reload Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Reload the mirror manifest",
    "tags": [
     "mirror"
    ],
    "description": "Reads the manifest of the mirror again and replaces the recorded artifacts with its content; every file must exist. Returns what was loaded. Permission `settings:manage`. Errors: `409 mirror_manifest_missing`, `422 mirror_manifest_invalid`. Audited as `mirror.reload` (outcome `failure` with the error code when the manifest is refused)."
   }
  },
  "/api/v1/navin-sm/discover": {
   "post": {
    "description": "Calls `GET <base>/v1/models` then `GET <base>/model/info` of the proxy (5 second timeout, TLS 1.2 or later, public roots plus the `ca_pem` given, no redirect) and returns `{models: [{id, context_window?, max_output_tokens?, vision?, reasoning?}], info_available, info_error}`. With `litellm_cluster_id` and `litellm_service`, the LiteLLM service installed by the Manager is read with its master key and the CA of the Manager, both kept in the server (an empty `base_url` then means its address); otherwise the key of the vault entry or the key typed for this call only. `/model/info` is optional (an admin route a virtual key may not reach). Permission `settings:manage`, plus `vault:manage` with a `shared_key_ref`. Errors: `422 navin_sm_base_url_invalid`, `422 navin_sm_header_invalid`, `422 navin_sm_litellm_link_incomplete` (one of the two link fields only), `422 navin_sm_litellm_source_not_found`, `409 navin_sm_master_key_missing`, `409 navin_sm_shared_key_missing`, `502 navin_sm_discover_failed` (details `reason`: timeout, tls_failed, refused, unreachable, auth_failed, not_found, http_status, protocol_error). Audited as `navin_sm.discover`.",
    "operationId": "discover_models_api_v1_navin_sm_discover_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DiscoverIn"
       }
      }
     },
     "required": true,
     "description": "The proxy to read."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Discover Models Api V1 Navin Sm Discover Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Discover the models of a LiteLLM proxy",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/distribution": {
   "get": {
    "description": "The release of Navin SM the catalog names (`service`: name, version, GitHub repository and tag, settings and CA paths per system), its packages with their published SHA256, stored state, size and download link, the number stored, the last ten fetches and whether one is running. Permission `settings:manage`; `409 navin_sm_service_missing` without the `navin-sm` service in the catalog.",
    "operationId": "distribution_api_v1_navin_sm_distribution_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Distribution Api V1 Navin Sm Distribution Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "State of the Navin SM distribution",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/distribution/checksums": {
   "post": {
    "description": "Records the published SHA256 of the packages from the lines `<sha256>  <filename>` of the SHA256SUMS and .sha256 files of the release, pasted together (offline sites). Returns `{updated, unchanged, conflicts, ignored}`: the files recorded or already identical, the stored packages whose SHA256 would change (reported and left as they are) and the names outside the release. Permission `settings:manage`. Errors: `409 navin_sm_service_missing`, `422 navin_sm_checksums_invalid` (no usable line). Audited as `navin_sm.package.checksums`.",
    "operationId": "load_checksums_api_v1_navin_sm_distribution_checksums_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ChecksumsIn"
       }
      }
     },
     "required": true,
     "description": "The checksum lines."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Load Checksums Api V1 Navin Sm Distribution Checksums Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Load the published checksums of the release",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/distribution/fetch": {
   "post": {
    "description": "Starts a background fetch of the release (`202`, the import): the checksum files first, then every package not stored yet, each verified against its published SHA256. The GitHub token is the API key of the vault entry, read in the server and never returned, logged or audited. Permissions `settings:manage` and `vault:manage`. Errors: `409 navin_sm_service_missing`, `422 navin_sm_vault_entry_not_found`, `422 navin_sm_github_token_missing`, `409 navin_sm_import_running`. Audited as `navin_sm.package.fetch` (name of the vault entry only). Follow it with `GET /navin-sm/distribution/imports/{import_id}`.",
    "operationId": "fetch_release_api_v1_navin_sm_distribution_fetch_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/FetchIn"
       }
      }
     },
     "required": true,
     "description": "The vault entry holding the GitHub token."
    },
    "responses": {
     "202": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Fetch Release Api V1 Navin Sm Distribution Fetch Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Fetch the release from GitHub",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/distribution/imports/{import_id}": {
   "get": {
    "description": "`{id, version, state, files, error, created_at, finished_at}`: `state` is `running`, `done` or `failed`; each file is `pending`, `downloading`, `stored`, `skipped` (already stored) or `failed` with its `error` (never the token). Permission `settings:manage`; `404 navin_sm_import_not_found`.",
    "operationId": "get_import_api_v1_navin_sm_distribution_imports__import_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "import_id",
      "required": true,
      "schema": {
       "title": "Import Id",
       "type": "string"
      },
      "description": "Identifier of the fetch, returned by `POST /navin-sm/distribution/fetch`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Import Api V1 Navin Sm Distribution Imports  Import Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "State of a fetch",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/distribution/packages/{filename}": {
   "delete": {
    "description": "Removes the stored file; its published SHA256 stays recorded. Answers `204`. Permission `settings:manage`. Errors: `404 navin_sm_package_unknown`, `404 navin_sm_package_missing`. Audited as `navin_sm.package.delete`.",
    "operationId": "delete_package_api_v1_navin_sm_distribution_packages__filename__delete",
    "parameters": [
     {
      "in": "path",
      "name": "filename",
      "required": true,
      "schema": {
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$",
       "title": "Filename",
       "type": "string"
      },
      "description": "File name of the package."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Remove a stored package",
    "tags": [
     "navin-sm"
    ]
   },
   "put": {
    "description": "Raw body of one package of the release, streamed to `<mirror_dir>/navin-sm/<version>/` and hashed while it is written; kept (`201`, the package as the distribution lists it) only when its SHA256 is the one published (loaded beforehand) or the one of the `X-Checksum-Sha256` header. Permission `settings:manage`. Errors: `404 navin_sm_package_unknown` (not a package of the release), `422 navin_sm_package_checksum_unknown` (no published SHA256 and no header), `422 navin_sm_package_checksum_mismatch` (the file is removed), `422 navin_sm_package_too_large` (2 GiB), `409 navin_sm_disk_full`. Audited as `navin_sm.package.store`, refusals included.",
    "operationId": "upload_package_api_v1_navin_sm_distribution_packages__filename__put",
    "parameters": [
     {
      "in": "path",
      "name": "filename",
      "required": true,
      "schema": {
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$",
       "title": "Filename",
       "type": "string"
      },
      "description": "File name of the package, as the catalog lists it for this version."
     },
     {
      "in": "header",
      "name": "X-Checksum-Sha256",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 64,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "X-Checksum-Sha256"
      },
      "description": "Expected SHA256 of the file (64 hexadecimal characters) when the published one was not loaded; it must match the published one when both exist."
     }
    ],
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Upload Package Api V1 Navin Sm Distribution Packages  Filename  Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Upload a package of the release",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/distribution/packages/{filename}/download": {
   "get": {
    "description": "The package as stored (`application/octet-stream`, `Cache-Control: no-store`), its SHA256 in the `X-Checksum-Sha256` header. Permission `settings:manage`. Errors: `404 navin_sm_package_unknown`, `404 navin_sm_package_missing` (not stored).",
    "operationId": "download_package_api_v1_navin_sm_distribution_packages__filename__download_get",
    "parameters": [
     {
      "in": "path",
      "name": "filename",
      "required": true,
      "schema": {
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$",
       "title": "Filename",
       "type": "string"
      },
      "description": "File name of the package."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/octet-stream": {
        "schema": {
         "format": "binary",
         "type": "string"
        }
       }
      },
      "description": "The package"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Download a stored package",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/litellm-sources": {
   "get": {
    "description": "LiteLLM services installed by the Manager with their address and the vault entry of their key, to prefill the gateway of a profile or link it (`litellm_cluster_id`, `litellm_service`). The vault entry is listed only to a holder of `vault:manage`; an installed service without an entry yet has `vault_entry_id` null (`POST /vault/import` creates it). Permission `settings:manage`.",
    "operationId": "litellm_sources_api_v1_navin_sm_litellm_sources_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Litellm Sources Api V1 Navin Sm Litellm Sources Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the installed LiteLLM gateways",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/profiles": {
   "get": {
    "description": "Profiles sorted by organization name, with the name of the vault entry of their shared key but never the key (`shared_key_set`). Permission `settings:manage`.",
    "operationId": "list_profiles_api_v1_navin_sm_profiles_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Profiles Api V1 Navin Sm Profiles Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the Navin SM profiles",
    "tags": [
     "navin-sm"
    ]
   },
   "post": {
    "operationId": "create_profile_api_v1_navin_sm_profiles_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ProfileIn"
       }
      }
     },
     "required": true,
     "description": "The profile."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Profile Api V1 Navin Sm Profiles Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create a Navin SM profile",
    "tags": [
     "navin-sm"
    ],
    "description": "Creates the profile and returns it (`201`). Permission `settings:manage`, plus `vault:manage` with a `shared_key_ref`. Errors (422 unless noted): `navin_sm_org_id_invalid`, `navin_sm_value_empty`, `navin_sm_value_duplicate`, `navin_sm_base_url_invalid`, `navin_sm_base_url_chat`, `navin_sm_shared_key_ref_required`, `navin_sm_shared_key_ref_forbidden`, `navin_sm_vault_entry_not_found`, `navin_sm_header_invalid`, `navin_sm_header_secret`, `navin_sm_models_count`, `navin_sm_model_duplicate`, `navin_sm_default_model_unknown`, `navin_sm_route_invalid`, `navin_sm_route_unknown`, `navin_sm_env_invalid`, `navin_sm_env_secret`, `409 navin_sm_org_taken`. Audited as `navin_sm.create`."
   }
  },
  "/api/v1/navin-sm/profiles/{profile_id}": {
   "delete": {
    "operationId": "delete_profile_api_v1_navin_sm_profiles__profile_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete a Navin SM profile",
    "tags": [
     "navin-sm"
    ],
    "description": "Deletes the profile (the vault entry of its key is kept). Answers `204`. Permission `settings:manage`; `404 navin_sm_profile_not_found`. Audited as `navin_sm.delete`."
   },
   "get": {
    "operationId": "get_profile_api_v1_navin_sm_profiles__profile_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Profile Api V1 Navin Sm Profiles  Profile Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a Navin SM profile",
    "tags": [
     "navin-sm"
    ],
    "description": "Returns one profile without any key. Permission `settings:manage`; `404 navin_sm_profile_not_found`."
   },
   "put": {
    "operationId": "update_profile_api_v1_navin_sm_profiles__profile_id__put",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ProfileIn"
       }
      }
     },
     "required": true,
     "description": "The whole profile."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Update Profile Api V1 Navin Sm Profiles  Profile Id  Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Replace a Navin SM profile",
    "tags": [
     "navin-sm"
    ],
    "description": "Replaces the whole profile and returns it. Same rules and errors as the creation, plus `404 navin_sm_profile_not_found`. Audited as `navin_sm.update` (names of the fields changed)."
   }
  },
  "/api/v1/navin-sm/profiles/{profile_id}/bundle": {
   "get": {
    "description": "Zip for one system (`navin-sm-<org_id>-<os>.zip`, `Cache-Control: no-store`): `managed-settings.json` (the shared key included, audited as `navin_sm.export` with purpose `bundle`), the CA of the Manager when the profile ships it (`use_manager_ca`), and the deployment files of the system: shell script and Ansible playbook on Linux, shell script and MDM notes on macOS, PowerShell script with GPO and Intune notes on Windows. The packages are downloaded apart (`GET /navin-sm/distribution/packages/{filename}/download`). Permission `settings:manage`, plus `vault:manage` for `shared_key`. Errors: `404 navin_sm_profile_not_found`, `409 navin_sm_service_missing` (no `navin-sm` service in the catalog), `409 navin_sm_shared_key_missing`.",
    "operationId": "profile_bundle_api_v1_navin_sm_profiles__profile_id__bundle_get",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     },
     {
      "in": "query",
      "name": "os",
      "required": true,
      "schema": {
       "pattern": "^(linux|macos|windows)$",
       "title": "Os",
       "type": "string"
      },
      "description": "System of the bundle: `linux`, `macos` or `windows`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/zip": {
        "schema": {
         "format": "binary",
         "type": "string"
        }
       }
      },
      "description": "The deployment bundle"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Download the deployment bundle of a profile",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/profiles/{profile_id}/export": {
   "get": {
    "description": "Returns the file as an attachment (`managed-settings.json`, `Cache-Control: no-store`), valid against the contract. `gateway.apiKey` is present only for `shared_key`, unsealed from the vault for this answer. Permission `settings:manage`, plus `vault:manage` for `shared_key`. Errors: `404 navin_sm_profile_not_found`, `409 navin_sm_shared_key_missing` (vault entry gone or without key), `422 navin_sm_os_required` (profile with `use_manager_ca` exported without `os`), `500 navin_sm_export_invalid`. Audited as `navin_sm.export` (never the key).",
    "operationId": "export_profile_api_v1_navin_sm_profiles__profile_id__export_get",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     },
     {
      "in": "query",
      "name": "os",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "pattern": "^(linux|macos|windows)$",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Os"
      },
      "description": "System the file is for (`linux`, `macos`, `windows`); required when the profile ships the CA of the Manager (`use_manager_ca`), since it fixes the path of `gateway.caBundle`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      },
      "description": "managed-settings.json of the profile"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Export the managed-settings.json of a profile",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/profiles/{profile_id}/keys": {
   "get": {
    "description": "LiteLLM virtual keys issued for the profile, active and blocked first, then revoked: assignee, alias, status, models and limits, never a key value nor its hash. Permission `navin_sm:keys`; `404 navin_sm_profile_not_found`.",
    "operationId": "list_keys_api_v1_navin_sm_profiles__profile_id__keys_get",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Keys Api V1 Navin Sm Profiles  Profile Id  Keys Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the virtual keys of a profile",
    "tags": [
     "navin-sm"
    ]
   },
   "post": {
    "description": "Issues a key at the LiteLLM service the profile is linked to (`POST /key/generate` with the master key kept in the server) for a user of the Manager or a group of the identity provider, and answers `201 {key, item}`: `key` is returned here and never again, the Manager keeps only the alias and the sha256 LiteLLM uses as identifier. The LiteLLM user is `navin-sm:<org_id>:<kind>:<assignee>`, the alias `navin-sm.<org_id>.<assignee>.<random>`. Permission `navin_sm:keys`. Errors: `404 navin_sm_profile_not_found`, `404 navin_sm_user_not_found`, `422 navin_sm_assignee_required`, `422 navin_sm_key_models_unknown` (a model outside the profile), `409 navin_sm_profile_not_linked`, `409 navin_sm_master_key_missing`, `409 navin_sm_key_alias_taken`, `502 navin_sm_proxy_refused` or `navin_sm_proxy_failed`. Audited as `navin_sm.key.create` (id and alias, never the key).",
    "operationId": "create_key_api_v1_navin_sm_profiles__profile_id__keys_post",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/KeyIn"
       }
      }
     },
     "required": true,
     "description": "Assignee, models and limits of the new key."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Key Api V1 Navin Sm Profiles  Profile Id  Keys Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Issue a virtual key",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/profiles/{profile_id}/keys/revoke-all": {
   "post": {
    "description": "Deletes every active or blocked key of the profile at the proxy in one call (`POST /key/delete`) and records them as revoked. Returns `{revoked, items}`. Permission `navin_sm:keys`. Errors: `404 navin_sm_profile_not_found`, `409 navin_sm_profile_not_linked`, `409 navin_sm_master_key_missing`, `502 navin_sm_proxy_refused` or `navin_sm_proxy_failed`. Audited as `navin_sm.key.revoke_all` (count and ids of the keys).",
    "operationId": "revoke_all_keys_api_v1_navin_sm_profiles__profile_id__keys_revoke_all_post",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Revoke All Keys Api V1 Navin Sm Profiles  Profile Id  Keys Revoke All Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Revoke every key of a profile",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/profiles/{profile_id}/keys/{key_id}": {
   "delete": {
    "description": "Deletes the key at the proxy (`POST /key/delete`, immediate) and keeps it in the Manager with status `revoked` and `revoked_at`; a key the proxy no longer knows is revoked all the same. Returns the key. Permission `navin_sm:keys`. Errors: `404 navin_sm_key_not_found`, `409 navin_sm_key_revoked`, `409 navin_sm_profile_not_linked`, `409 navin_sm_master_key_missing`, `502 navin_sm_proxy_refused` or `navin_sm_proxy_failed`. Audited as `navin_sm.key.revoke`.",
    "operationId": "revoke_key_api_v1_navin_sm_profiles__profile_id__keys__key_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     },
     {
      "in": "path",
      "name": "key_id",
      "required": true,
      "schema": {
       "title": "Key Id",
       "type": "string"
      },
      "description": "Identifier of the key in the Manager."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Revoke Key Api V1 Navin Sm Profiles  Profile Id  Keys  Key Id  Delete",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Revoke a key",
    "tags": [
     "navin-sm"
    ]
   },
   "put": {
    "description": "Applies the models and limits at the proxy (`POST /key/update`), then in the Manager, and returns the key. Permission `navin_sm:keys`. Errors: `404 navin_sm_profile_not_found`, `404 navin_sm_key_not_found`, `409 navin_sm_key_revoked`, `409 navin_sm_key_gone` (the proxy no longer knows the key, which is then recorded as revoked), `422 navin_sm_key_models_unknown`, `409 navin_sm_profile_not_linked`, `409 navin_sm_master_key_missing`, `502 navin_sm_proxy_refused` or `navin_sm_proxy_failed`. Audited as `navin_sm.key.update`.",
    "operationId": "update_key_api_v1_navin_sm_profiles__profile_id__keys__key_id__put",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     },
     {
      "in": "path",
      "name": "key_id",
      "required": true,
      "schema": {
       "title": "Key Id",
       "type": "string"
      },
      "description": "Identifier of the key in the Manager (never its value)."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/KeyLimitsIn"
       }
      }
     },
     "required": true,
     "description": "New models and limits."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Update Key Api V1 Navin Sm Profiles  Profile Id  Keys  Key Id  Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Change the models and limits of a key",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/profiles/{profile_id}/keys/{key_id}/block": {
   "post": {
    "description": "Blocks the key at the proxy (`POST /key/block`): it is refused at once and can be unblocked. Returns the key with status `blocked`. Permission `navin_sm:keys`. Errors: `404 navin_sm_key_not_found`, `409 navin_sm_key_revoked`, `409 navin_sm_key_gone`, `409 navin_sm_profile_not_linked`, `409 navin_sm_master_key_missing`, `502 navin_sm_proxy_refused` or `navin_sm_proxy_failed`. Audited as `navin_sm.key.block`.",
    "operationId": "block_key_api_v1_navin_sm_profiles__profile_id__keys__key_id__block_post",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     },
     {
      "in": "path",
      "name": "key_id",
      "required": true,
      "schema": {
       "title": "Key Id",
       "type": "string"
      },
      "description": "Identifier of the key in the Manager."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Block Key Api V1 Navin Sm Profiles  Profile Id  Keys  Key Id  Block Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Block a key",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/profiles/{profile_id}/keys/{key_id}/unblock": {
   "post": {
    "description": "Unblocks a blocked key at the proxy (`POST /key/unblock`) and returns it with status `active`. Permission `navin_sm:keys`. Same errors as the block. Audited as `navin_sm.key.unblock`.",
    "operationId": "unblock_key_api_v1_navin_sm_profiles__profile_id__keys__key_id__unblock_post",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     },
     {
      "in": "path",
      "name": "key_id",
      "required": true,
      "schema": {
       "title": "Key Id",
       "type": "string"
      },
      "description": "Identifier of the key in the Manager."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Unblock Key Api V1 Navin Sm Profiles  Profile Id  Keys  Key Id  Unblock Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Unblock a key",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/profiles/{profile_id}/preview": {
   "get": {
    "description": "The file the export would produce, checked against the contract, without its key: a `shared_key` is replaced by `<vault: entry name>`. Returns `{os, settings_path, ca_path, document, problems, valid}`; `problems` lists the rules the document breaks (a vault entry without key, a profile with `use_manager_ca` previewed without `os`). Permission `settings:manage`; `404 navin_sm_profile_not_found`. Not audited (nothing leaves the server).",
    "operationId": "preview_profile_api_v1_navin_sm_profiles__profile_id__preview_get",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     },
     {
      "in": "query",
      "name": "os",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "pattern": "^(linux|macos|windows)$",
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Os"
      },
      "description": "System the file is for (`linux`, `macos`, `windows`): fixes `settings_path` and, with `use_manager_ca`, the path of `gateway.caBundle`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Preview Profile Api V1 Navin Sm Profiles  Profile Id  Preview Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Preview the managed-settings.json of a profile",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/profiles/{profile_id}/usage": {
   "get": {
    "description": "Reads the proxy through the server (`GET /key/info` per live key, `GET /spend/logs` over the period) and returns `{available, reason, period, keys, models, totals, truncated, last_use}`: for each key its live state, spend, budget and reset date, and over the period its calls, tokens, errors, models and last use; the same figures per model and in total. `truncated` is true when the proxy capped the logs at 10000 rows (the figures of the period are then partial). When the profile is not linked, the master key is missing or the proxy is out of reach, `available` is false with `reason` and no figure: zeros are never invented. Permission `navin_sm:keys`; `404 navin_sm_profile_not_found`.",
    "operationId": "usage_api_v1_navin_sm_profiles__profile_id__usage_get",
    "parameters": [
     {
      "in": "path",
      "name": "profile_id",
      "required": true,
      "schema": {
       "title": "Profile Id",
       "type": "string"
      },
      "description": "Identifier of the profile."
     },
     {
      "in": "query",
      "name": "days",
      "required": false,
      "schema": {
       "default": 30,
       "maximum": 366,
       "minimum": 1,
       "title": "Days",
       "type": "integer"
      },
      "description": "Length of the period in days, 1 to 366 (default 30), ending today."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Usage Api V1 Navin Sm Profiles  Profile Id  Usage Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Tracking of the keys of a profile",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/navin-sm/users": {
   "get": {
    "description": "Enabled users of the Manager (50 at most, sorted by name) whose user name, display name or email contains `q`, with `id`, `username`, `display_name`, `email` and `source`. Permission `navin_sm:keys`.",
    "operationId": "assignable_users_api_v1_navin_sm_users_get",
    "parameters": [
     {
      "in": "query",
      "name": "q",
      "required": false,
      "schema": {
       "default": "",
       "maxLength": 100,
       "title": "Q",
       "type": "string"
      },
      "description": "Text searched in the user name, display name and email (100 characters at most)."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Assignable Users Api V1 Navin Sm Users Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the users a key can be assigned to",
    "tags": [
     "navin-sm"
    ]
   }
  },
  "/api/v1/notification-targets": {
   "get": {
    "operationId": "list_targets_api_v1_notification_targets_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Targets Api V1 Notification Targets Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the notification targets",
    "tags": [
     "alerts"
    ],
    "description": "Every target with its `kind`, `config`, `min_severity`, `enabled` and whether an HMAC secret is set (never its value). Permission `alerts:manage`."
   },
   "post": {
    "operationId": "create_target_api_v1_notification_targets_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__alerts__TargetIn"
       }
      }
     },
     "required": true,
     "description": "Name, kind, configuration and minimum severity of the target."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Target Api V1 Notification Targets Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Add a notification target",
    "tags": [
     "alerts"
    ],
    "description": "Creates a target and returns it (`201`). An email target needs `config.to`, a webhook target `config.url` (`http://` or `https://`); a syslog target uses the syslog server of the settings. Permission `alerts:manage`; `422 notification_target_invalid`. Audited as `notification_target.create`."
   }
  },
  "/api/v1/notification-targets/{target_id}": {
   "delete": {
    "operationId": "delete_target_api_v1_notification_targets__target_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "target_id",
      "required": true,
      "schema": {
       "title": "Target Id",
       "type": "string"
      },
      "description": "Identifier of the notification target."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete a notification target",
    "tags": [
     "alerts"
    ],
    "description": "Deletes the target. Answers `204`. Permission `alerts:manage`; `404 notification_target_not_found`. Audited as `notification_target.delete`."
   },
   "patch": {
    "operationId": "patch_target_api_v1_notification_targets__target_id__patch",
    "parameters": [
     {
      "in": "path",
      "name": "target_id",
      "required": true,
      "schema": {
       "title": "Target Id",
       "type": "string"
      },
      "description": "Identifier of the notification target."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/navin_manager__api__alerts__TargetPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the target to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Patch Target Api V1 Notification Targets  Target Id  Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update a notification target",
    "tags": [
     "alerts"
    ],
    "description": "Changes the fields given and returns the target. Permission `alerts:manage`. Errors: `404 notification_target_not_found`, `422 notification_target_invalid`. Audited as `notification_target.update`."
   }
  },
  "/api/v1/notification-targets/{target_id}/test": {
   "post": {
    "operationId": "test_target_api_v1_notification_targets__target_id__test_post",
    "parameters": [
     {
      "in": "path",
      "name": "target_id",
      "required": true,
      "schema": {
       "title": "Target Id",
       "type": "string"
      },
      "description": "Identifier of the notification target."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Test Target Api V1 Notification Targets  Target Id  Test Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Send a test notification",
    "tags": [
     "alerts"
    ],
    "description": "Sends a test message (state `warning`, fingerprint `test`) to the target now and returns `{\"ok\": true}`. Permission `alerts:manage`. Errors: `404 notification_target_not_found`, `502 notification_failed` (the target refused or could not be reached). Audited as `notification_target.test`."
   }
  },
  "/api/v1/operations/running": {
   "get": {
    "operationId": "running_api_v1_operations_running_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Running Api V1 Operations Running Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the running operations",
    "tags": [
     "operations"
    ],
    "description": "Pending and running operations of every cluster where the caller holds `operations:read` (at most 200, newest first), with their `count`. Used by the activity indicator of the console."
   }
  },
  "/api/v1/operations/{operation_id}": {
   "get": {
    "operationId": "get_operation_api_v1_operations__operation_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "operation_id",
      "required": true,
      "schema": {
       "title": "Operation Id",
       "type": "string"
      },
      "description": "Identifier of the operation (an install, a restart, a backup...) whose tasks run on the hosts."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Operation Api V1 Operations  Operation Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get an operation with its stages and tasks",
    "tags": [
     "operations"
    ],
    "description": "Returns the operation and its `stages` in order; each stage gives `seq`, `name_i18n`, `status`, `tolerate_failures` and its `tasks` (host, type, service, component, status, attempts, exit code, summary, error, times). Permission `operations:read` on its cluster; `404 operation_not_found`."
   }
  },
  "/api/v1/operations/{operation_id}/abort": {
   "post": {
    "operationId": "abort_api_v1_operations__operation_id__abort_post",
    "parameters": [
     {
      "in": "path",
      "name": "operation_id",
      "required": true,
      "schema": {
       "title": "Operation Id",
       "type": "string"
      },
      "description": "Identifier of the operation (an install, a restart, a backup...) whose tasks run on the hosts."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Abort Api V1 Operations  Operation Id  Abort Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Abort an operation",
    "tags": [
     "operations"
    ],
    "description": "Asks a pending or running operation to stop: tasks not started are cancelled, the running ones are stopped by their agents. Returns `id`, `status` and `abort_requested`. Permission `operations:abort`; `409 operation_not_running` when it is already finished. Audited as `operation.abort`."
   }
  },
  "/api/v1/operations/{operation_id}/retry": {
   "post": {
    "operationId": "retry_api_v1_operations__operation_id__retry_post",
    "parameters": [
     {
      "in": "path",
      "name": "operation_id",
      "required": true,
      "schema": {
       "title": "Operation Id",
       "type": "string"
      },
      "description": "Identifier of the operation (an install, a restart, a backup...) whose tasks run on the hosts."
     },
     {
      "in": "query",
      "name": "approval_id",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Approval Id"
      },
      "description": "Approval granted for the new operation under `banking-secure`, used once; omit it to use the approval granted to you."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Retry Api V1 Operations  Operation Id  Retry Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Retry a failed operation",
    "tags": [
     "operations"
    ],
    "description": "Creates a new operation from a `failed` or `aborted` one and returns its `operation_id`. The retry goes through the checks of a new operation: one change at a time per service, administrative state of the service, profile of the cluster and, under `banking-secure`, a new approval for a disruptive operation. Permission `operations:abort`; `409 operation_not_retryable` in any other status. Audited as `operation.retry`."
   }
  },
  "/api/v1/operations/{operation_id}/tasks/{task_id}": {
   "get": {
    "operationId": "get_task_api_v1_operations__operation_id__tasks__task_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "operation_id",
      "required": true,
      "schema": {
       "title": "Operation Id",
       "type": "string"
      },
      "description": "Identifier of the operation (an install, a restart, a backup...) whose tasks run on the hosts."
     },
     {
      "in": "path",
      "name": "task_id",
      "required": true,
      "schema": {
       "title": "Task Id",
       "type": "string"
      },
      "description": "Identifier of the task, from the stages of the operation."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Task Api V1 Operations  Operation Id  Tasks  Task Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a task of an operation",
    "tags": [
     "operations"
    ],
    "description": "Returns one task with its full `output`, `attempts` and `max_attempts`, `timeout_s`, `exit_code`, `duration_ms` and times. Permission `operations:read`; `404 operation_not_found` or `404 task_not_found`."
   }
  },
  "/api/v1/operations/{operation_id}/tasks/{task_id}/logs": {
   "get": {
    "operationId": "task_logs_api_v1_operations__operation_id__tasks__task_id__logs_get",
    "parameters": [
     {
      "in": "path",
      "name": "operation_id",
      "required": true,
      "schema": {
       "title": "Operation Id",
       "type": "string"
      },
      "description": "Identifier of the operation (an install, a restart, a backup...) whose tasks run on the hosts."
     },
     {
      "in": "path",
      "name": "task_id",
      "required": true,
      "schema": {
       "title": "Task Id",
       "type": "string"
      },
      "description": "Identifier of the task."
     },
     {
      "in": "query",
      "name": "after_seq",
      "required": false,
      "schema": {
       "default": -1,
       "minimum": -1,
       "title": "After Seq",
       "type": "integer"
      },
      "description": "Return the lines whose sequence number is greater than this one. Default -1 (from the first line)."
     },
     {
      "in": "query",
      "name": "limit",
      "required": false,
      "schema": {
       "default": 1000,
       "maximum": 5000,
       "minimum": 1,
       "title": "Limit",
       "type": "integer"
      },
      "description": "Maximum number of lines, from 1 to 5000. Default 1000."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Task Logs Api V1 Operations  Operation Id  Tasks  Task Id  Logs Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Read the log lines of a task",
    "tags": [
     "operations"
    ],
    "description": "Returns the `lines` written after `after_seq` (each with `seq`, `ts`, `stream` and `data`), `next_seq` to pass\nas `after_seq` on the next call, and `done`: true once the task is finished and every line was read. To follow a\ntask, call it again with `after_seq=next_seq` until `done`. Permission `operations:read`."
   }
  },
  "/api/v1/pki/ca": {
   "get": {
    "operationId": "get_ca_api_v1_pki_ca_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Ca Api V1 Pki Ca Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the certificate authority",
    "tags": [
     "pki"
    ],
    "description": "Returns the CA certificate of the Manager (`ca_pem`), its expiry `not_after` and its `sha256` fingerprint. Any signed in user."
   }
  },
  "/api/v1/profiles": {
   "get": {
    "operationId": "list_profiles_api_v1_profiles_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response List Profiles Api V1 Profiles Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the installation profiles",
    "tags": [
     "lifecycle"
    ],
    "description": "Every profile with its label and description in both languages, its rules, whether it requires approvals and the severity of the network rules. Any signed in user."
   }
  },
  "/api/v1/restore-targets": {
   "get": {
    "operationId": "list_restore_targets_api_v1_restore_targets_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Restore Targets Api V1 Restore Targets Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the restore destinations",
    "tags": [
     "backup"
    ],
    "description": "The restore destinations declared by the operator in the `restore_targets` setting: name, environment, kind (`pg_dump`) and declared versions. Connection strings and secret variable names never leave the server. Permission `restore:execute`."
   }
  },
  "/api/v1/restore-tests": {
   "get": {
    "operationId": "list_restore_tests_api_v1_restore_tests_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Restore Tests Api V1 Restore Tests Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the restore tests",
    "tags": [
     "backup"
    ],
    "description": "The last 200 restore tests with their outcome and signed report. Permission `backup:read`."
   }
  },
  "/api/v1/restores": {
   "get": {
    "operationId": "list_restores_api_v1_restores_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Restores Api V1 Restores Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the restore plans",
    "tags": [
     "backup"
    ],
    "description": "The last 200 restore plans with their status and number of approvals. Permission `backup:read`."
   }
  },
  "/api/v1/restores/plan": {
   "post": {
    "operationId": "plan_restore_api_v1_restores_plan_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RestorePlanIn"
       }
      }
     },
     "required": true,
     "description": "Artefact, environment, destination and target versions."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Plan Restore Api V1 Restores Plan Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Plan a restore",
    "tags": [
     "backup"
    ],
    "description": "Creates a restore plan for a backup artefact: checks the compatibility of the backed up versions with the target versions (same major version) and lists the steps (verify artefact, verify destination, restore, verify restored). With `target_name`, the artefact must be an available `pg_dump` with a `verification_inventory` and the destination an empty PostgreSQL database owned by a restricted role; its identity is frozen in `target_snapshot`. Returns the plan (`201`). Permission `restore:execute`. Errors: `404 backup_artifact_not_found`, `501 restore_executor_unavailable` (unknown destination), `409 restore_target_invalid`, `409 restore_target_not_empty`, `422 restore_inventory_required`. Audited as `restore.plan`."
   }
  },
  "/api/v1/restores/{plan_id}": {
   "get": {
    "operationId": "get_restore_api_v1_restores__plan_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "plan_id",
      "required": true,
      "schema": {
       "title": "Plan Id",
       "type": "string"
      },
      "description": "Identifier of the restore plan."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Restore Api V1 Restores  Plan Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a restore plan",
    "tags": [
     "backup"
    ],
    "description": "Returns the plan with its compatibility, steps, `approvers` and `required_approvals` (2). Permission `backup:read`; `404 restore_plan_not_found`."
   }
  },
  "/api/v1/restores/{plan_id}/approve": {
   "post": {
    "operationId": "approve_restore_api_v1_restores__plan_id__approve_post",
    "parameters": [
     {
      "in": "path",
      "name": "plan_id",
      "required": true,
      "schema": {
       "title": "Plan Id",
       "type": "string"
      },
      "description": "Identifier of the restore plan."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Approve Restore Api V1 Restores  Plan Id  Approve Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Approve a restore plan",
    "tags": [
     "backup"
    ],
    "description": "Adds the approval of the caller; two approvals by people other than the requester are needed. Permission `restore:execute`. Errors: `403 restore_self_approval`, `409 restore_not_approvable`. Audited as `restore.approve`."
   }
  },
  "/api/v1/restores/{plan_id}/dry-run": {
   "post": {
    "operationId": "dry_run_restore_api_v1_restores__plan_id__dry_run_post",
    "parameters": [
     {
      "in": "path",
      "name": "plan_id",
      "required": true,
      "schema": {
       "title": "Plan Id",
       "type": "string"
      },
      "description": "Identifier of the restore plan."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Dry Run Restore Api V1 Restores  Plan Id  Dry Run Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Dry run a restore plan",
    "tags": [
     "backup"
    ],
    "description": "Checks the digest, decryption and compatibility without writing to the destination, and returns the recorded approvers. For a named destination it also checks its identity, emptiness and restricted role (`checks.destination`, `checks.executor`). A successful dry run does not authorize execution: two approvals are still required. Permission `restore:execute`. Audited as `restore.dry_run`."
   }
  },
  "/api/v1/restores/{plan_id}/execute": {
   "post": {
    "operationId": "execute_restore_api_v1_restores__plan_id__execute_post",
    "parameters": [
     {
      "in": "path",
      "name": "plan_id",
      "required": true,
      "schema": {
       "title": "Plan Id",
       "type": "string"
      },
      "description": "Identifier of the restore plan."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Execute Restore Api V1 Restores  Plan Id  Execute Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Execute an approved restore",
    "tags": [
     "backup"
    ],
    "description": "Runs an approved plan with a destination: status `executing` and a durable `execution_token` are committed before any write. The artefact is checked again (size, digest, decryption), restored with `pg_restore --single-transaction` by the restricted role, then its rows are read back and compared with the backup inventory (`result.inventory`, `rows`, `tables`). Success: `executed`. Recorded failure: `failed`, `rollback_performed: false`, HTTP `502 restore_execution_failed`; its nested `result.error` identifies the cause, including `backup_corrupted`, `restore_target_busy` or `restore_execution_timeout`. A process interruption can leave `executing` for manual inspection. Nothing is automatically rolled back or replayed. Pre-execution refusals include `409 restore_not_approved`, `501 restore_executor_unavailable` and `409 restore_target_changed`. Permission `restore:execute`. Audited as `restore.execute.started` and `restore.execute`."
   }
  },
  "/api/v1/roles": {
   "get": {
    "operationId": "roles_api_v1_roles_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "additionalProperties": true,
          "type": "object"
         },
         "title": "Response Roles Api V1 Roles Get",
         "type": "array"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the roles and their permissions",
    "tags": [
     "users"
    ],
    "description": "Every role with its `name`, its `label` in both languages, its sorted `permissions` and its `scopes` (`global`, and `cluster` when it can be bound to one cluster). Permission `users:read`."
   }
  },
  "/api/v1/settings": {
   "get": {
    "description": "Returns `site_name`, `default_language`, `install`, `smtp`, `syslog`, `retention` and `proxy`, secrets masked. Any signed in user.",
    "operationId": "get_settings_view_api_v1_settings_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Settings View Api V1 Settings Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the settings",
    "tags": [
     "settings"
    ]
   },
   "put": {
    "operationId": "put_settings_api_v1_settings_put",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SettingsBody"
       }
      }
     },
     "required": true,
     "description": "Sections of the settings to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Put Settings Api V1 Settings Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update the settings",
    "tags": [
     "settings"
    ],
    "description": "Changes the sections and fields given; a section or field left out is kept. Returns the settings. Permission `settings:manage`. Errors: `422 proxy_invalid` (proxy URL with credentials or not http(s)), `422 validation_error`. Audited as `settings.update`."
   }
  },
  "/api/v1/stack": {
   "get": {
    "operationId": "stack_api_v1_stack_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Stack Api V1 Stack Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the catalog summary",
    "tags": [
     "stack"
    ],
    "description": "Name, version and categories of the stack and a summary of every service it offers (components, modes, dependencies, licence). Any signed in user."
   }
  },
  "/api/v1/stack/services/{name}": {
   "get": {
    "operationId": "service_api_v1_stack_services__name__get",
    "parameters": [
     {
      "in": "path",
      "name": "name",
      "required": true,
      "schema": {
       "title": "Name",
       "type": "string"
      },
      "description": "Name of the catalog service, for example `postgresql`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Service Api V1 Stack Services  Name  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a catalog service",
    "tags": [
     "stack"
    ],
    "description": "Public description of one catalog service: components, modes, methods, delivery, layer and high availability. Any signed in user; `404` for an unknown service."
   }
  },
  "/api/v1/system/health": {
   "get": {
    "operationId": "health_api_v1_system_health_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Health Api V1 System Health Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the health of the Manager",
    "tags": [
     "system"
    ],
    "description": "Returns `version`, `database` (`ok`, `latency_ms`), `engine` (`leader`, `last_tick_at`, `lag_s`, `queued_tasks`), `agents` (`online`: heartbeat in the last 60 seconds, `lost`, `total`) and `scheduler.jobs` (last run and last error of each job). Permission `system:read`."
   }
  },
  "/api/v1/system/supported-os": {
   "get": {
    "description": "Published list of the operating systems and versions the agents and the services support. Any signed in user.",
    "operationId": "supported_os_api_v1_system_supported_os_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Supported Os Api V1 System Supported Os Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the supported operating systems",
    "tags": [
     "system"
    ]
   }
  },
  "/api/v1/telemetry": {
   "get": {
    "description": "Returns `enabled`, `database`, `flush_seconds`, `retention_days`, `stats` (`buffered`, `written`, `dropped`, `failures`, `last_error`) and the exported `tables`. Permission `cluster:read` on at least one cluster.",
    "operationId": "telemetry_api_v1_telemetry_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Telemetry Api V1 Telemetry Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the telemetry export state",
    "tags": [
     "telemetry"
    ]
   }
  },
  "/api/v1/users": {
   "get": {
    "operationId": "list_users_api_v1_users_get",
    "parameters": [
     {
      "in": "query",
      "name": "limit",
      "required": false,
      "schema": {
       "default": 50,
       "maximum": 500,
       "minimum": 1,
       "title": "Limit",
       "type": "integer"
      },
      "description": "Maximum number of users in the page, from 1 to 500. Default 50."
     },
     {
      "in": "query",
      "name": "cursor",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 200,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Cursor"
      },
      "description": "The `next_cursor` of the previous page (the last username, lower case). Omit it for the first page."
     },
     {
      "in": "query",
      "name": "q",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "maxLength": 100,
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Q"
      },
      "description": "Text searched, case insensitive, in the username, the display name and the email."
     },
     {
      "in": "query",
      "name": "source",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "enum": [
          "local",
          "ldap",
          "oidc"
         ],
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Source"
      },
      "description": "Only the users of this source: `local`, `ldap` or `oidc`."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Users Api V1 Users Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "List the users",
    "tags": [
     "users"
    ],
    "description": "Users sorted by username, each with its role bindings, MFA state, lock and last sign in. Paginated with `limit` and `cursor`. Permission `users:read`."
   },
   "post": {
    "operationId": "create_user_api_v1_users_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UserCreate"
       }
      }
     },
     "required": true,
     "description": "The new account."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create User Api V1 Users Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Create a local user",
    "tags": [
     "users"
    ],
    "description": "Creates a local account with its password and role bindings and returns it (`201`). Permission `users:manage`. Errors: `409 username_taken`, `422 password_policy`, `422 role_invalid`, `422 role_global_only`, `422 binding_cluster_not_found`, `403 user_manage_denied` (granting `admin` without being a full administrator). Audited as `user.create`."
   }
  },
  "/api/v1/users/{user_id}": {
   "delete": {
    "operationId": "delete_user_api_v1_users__user_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "user_id",
      "required": true,
      "schema": {
       "title": "User Id",
       "type": "string"
      },
      "description": "Identifier of the user account of the console."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete a user",
    "tags": [
     "users"
    ],
    "description": "Deletes the account. Answers `204`. Permission `users:manage`. Errors: `404 user_not_found`, `409 cannot_delete_self`, `409 last_admin`, `403 user_manage_denied`. Audited as `user.delete`."
   },
   "get": {
    "operationId": "get_user_api_v1_users__user_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "user_id",
      "required": true,
      "schema": {
       "title": "User Id",
       "type": "string"
      },
      "description": "Identifier of the user account of the console."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get User Api V1 Users  User Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a user",
    "tags": [
     "users"
    ],
    "description": "Returns the account with its role bindings (`role`, `cluster_id`, `source`). Permission `users:read`; `404 user_not_found`."
   },
   "patch": {
    "operationId": "patch_user_api_v1_users__user_id__patch",
    "parameters": [
     {
      "in": "path",
      "name": "user_id",
      "required": true,
      "schema": {
       "title": "User Id",
       "type": "string"
      },
      "description": "Identifier of the user account of the console."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UserPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the user to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Patch User Api V1 Users  User Id  Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update or disable a user",
    "tags": [
     "users"
    ],
    "description": "Changes the fields given, keeps the others, and returns the user. Disabling an account revokes its sessions at once. Permission `users:manage`. Errors: `404 user_not_found`, `409 cannot_disable_self`, `409 last_admin`, `403 user_manage_denied`. Audited as `user.update`."
   }
  },
  "/api/v1/users/{user_id}/mfa/reset": {
   "post": {
    "operationId": "reset_mfa_api_v1_users__user_id__mfa_reset_post",
    "parameters": [
     {
      "in": "path",
      "name": "user_id",
      "required": true,
      "schema": {
       "title": "User Id",
       "type": "string"
      },
      "description": "Identifier of the user account of the console."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Reset Mfa Api V1 Users  User Id  Mfa Reset Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Reset the second factor of a user",
    "tags": [
     "users"
    ],
    "description": "Turns MFA off for the user, deletes its secret and recovery codes and revokes its sessions; the user enrolls again at the next sign in when its role requires MFA. Returns the user. Permission `users:manage`. Audited as `user.mfa_reset`."
   }
  },
  "/api/v1/users/{user_id}/password": {
   "post": {
    "operationId": "reset_password_api_v1_users__user_id__password_post",
    "parameters": [
     {
      "in": "path",
      "name": "user_id",
      "required": true,
      "schema": {
       "title": "User Id",
       "type": "string"
      },
      "description": "Identifier of the user account of the console."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PasswordReset"
       }
      }
     },
     "required": true,
     "description": "The new password and whether it must be changed at the next sign in."
    },
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Set the password of a local user",
    "tags": [
     "users"
    ],
    "description": "Sets a new password following the policy, unlocks the account and revokes its sessions. Answers `204`. Permission `users:manage`. Errors: `409 not_local_user`, `422 password_policy`, `404 user_not_found`, `403 user_manage_denied`. Audited as `user.password_reset`."
   }
  },
  "/api/v1/users/{user_id}/roles": {
   "put": {
    "description": "Replaces the manual bindings by the list given; bindings synchronized from LDAP or OIDC are kept. When a new role requires MFA and the user has none, its sessions are revoked. Returns the user. Permission `users:manage`. Errors: `409 last_admin`, `422 role_invalid`, `422 role_global_only`, `422 binding_cluster_not_found`, `403 user_manage_denied`. Audited as `user.roles` with the bindings before and after.",
    "operationId": "put_roles_api_v1_users__user_id__roles_put",
    "parameters": [
     {
      "in": "path",
      "name": "user_id",
      "required": true,
      "schema": {
       "title": "User Id",
       "type": "string"
      },
      "description": "Identifier of the user account of the console."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RolesBody"
       }
      }
     },
     "required": true,
     "description": "The complete list of manual bindings."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Put Roles Api V1 Users  User Id  Roles Put",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Replace the role bindings of a user",
    "tags": [
     "users"
    ]
   }
  },
  "/api/v1/users/{user_id}/unlock": {
   "post": {
    "operationId": "unlock_user_api_v1_users__user_id__unlock_post",
    "parameters": [
     {
      "in": "path",
      "name": "user_id",
      "required": true,
      "schema": {
       "title": "User Id",
       "type": "string"
      },
      "description": "Identifier of the user account of the console."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Unlock User Api V1 Users  User Id  Unlock Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Unlock a user",
    "tags": [
     "users"
    ],
    "description": "Clears the lock set after repeated failed sign ins and resets the failure counter. Returns the user. Permission `users:manage`. Audited as `user.unlock`."
   }
  },
  "/api/v1/vault/entries": {
   "get": {
    "description": "Services of the vault sorted by name, with their URL and login but without their password nor key. Permission `vault:manage`.",
    "operationId": "list_entries_api_v1_vault_entries_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response List Entries Api V1 Vault Entries Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "List the vault entries",
    "tags": [
     "vault"
    ]
   },
   "post": {
    "operationId": "create_entry_api_v1_vault_entries_post",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/EntryIn"
       }
      }
     },
     "required": true,
     "description": "The service and its credentials."
    },
    "responses": {
     "201": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Create Entry Api V1 Vault Entries Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Add a vault entry",
    "tags": [
     "vault"
    ],
    "description": "Creates a manual entry and returns it (`201`). Permission `vault:manage`. Errors: `409 vault_name_taken`, `422 vault_name_required`. Audited as `vault.create`."
   }
  },
  "/api/v1/vault/entries/{entry_id}": {
   "delete": {
    "operationId": "delete_entry_api_v1_vault_entries__entry_id__delete",
    "parameters": [
     {
      "in": "path",
      "name": "entry_id",
      "required": true,
      "schema": {
       "title": "Entry Id",
       "type": "string"
      },
      "description": "Identifier of the vault entry."
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Delete a vault entry",
    "tags": [
     "vault"
    ],
    "description": "Deletes the entry. Answers `204`. Permission `vault:manage`; `404 vault_entry_not_found`. Audited as `vault.delete`."
   },
   "get": {
    "operationId": "get_entry_api_v1_vault_entries__entry_id__get",
    "parameters": [
     {
      "in": "path",
      "name": "entry_id",
      "required": true,
      "schema": {
       "title": "Entry Id",
       "type": "string"
      },
      "description": "Identifier of the vault entry."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Get Entry Api V1 Vault Entries  Entry Id  Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Get a vault entry",
    "tags": [
     "vault"
    ],
    "description": "Returns the sheet of one entry without its password nor key. Permission `vault:manage`; `404 vault_entry_not_found`."
   },
   "patch": {
    "operationId": "update_entry_api_v1_vault_entries__entry_id__patch",
    "parameters": [
     {
      "in": "path",
      "name": "entry_id",
      "required": true,
      "schema": {
       "title": "Entry Id",
       "type": "string"
      },
      "description": "Identifier of the vault entry."
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/EntryPatch"
       }
      }
     },
     "required": true,
     "description": "Fields of the entry to change."
    },
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Update Entry Api V1 Vault Entries  Entry Id  Patch",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Update a vault entry",
    "tags": [
     "vault"
    ],
    "description": "Changes the fields given and returns the entry. Permission `vault:manage`. Errors: `404 vault_entry_not_found`, `409 vault_name_taken`, `422 vault_name_required`, `409 vault_entry_managed` (credentials of a console the Manager rotates). Audited as `vault.update` (field names only)."
   }
  },
  "/api/v1/vault/entries/{entry_id}/reveal": {
   "post": {
    "description": "Returns the password and the key of one service in clear, to show and copy them in the console. Permission `vault:manage`; `404 vault_entry_not_found`. Audited as `vault.reveal` (service name only).",
    "operationId": "reveal_entry_api_v1_vault_entries__entry_id__reveal_post",
    "parameters": [
     {
      "in": "path",
      "name": "entry_id",
      "required": true,
      "schema": {
       "title": "Entry Id",
       "type": "string"
      },
      "description": "Identifier of the vault entry."
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Reveal Entry Api V1 Vault Entries  Entry Id  Reveal Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     },
     "422": {
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      },
      "description": "Validation Error"
     }
    },
    "summary": "Reveal the password and key of an entry",
    "tags": [
     "vault"
    ]
   }
  },
  "/api/v1/vault/import": {
   "post": {
    "description": "Creates or refreshes the entries of the installed services of every cluster; fields changed by hand are kept. Returns the names of the entries by outcome. Permission `vault:manage`. Audited as `vault.import`.",
    "operationId": "import_entries_api_v1_vault_import_post",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": {
          "items": {
           "type": "string"
          },
          "type": "array"
         },
         "title": "Response Import Entries Api V1 Vault Import Post",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Import the credentials of the installed services",
    "tags": [
     "vault"
    ]
   }
  },
  "/api/v1/version": {
   "get": {
    "operationId": "version_api_v1_version_get",
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "additionalProperties": true,
         "title": "Response Version Api V1 Version Get",
         "type": "object"
        }
       }
      },
      "description": "Successful Response"
     }
    },
    "summary": "Get the version of the Manager",
    "tags": [
     "meta"
    ],
    "description": "Returns `name` (`navin-manager`), `version`, `environment` and the `stack` of the catalog (`name`, `version`, number of `services`). Public."
   }
  }
 },
 "tags": [
  {
   "name": "agent",
   "x-displayName": "Agent",
   "description": "Registration of a new Navin agent. The agent is the small daemon installed on every host the Manager drives: it\nreports the facts and metrics of the host and runs the tasks of the operations. All its other calls (heartbeats,\ntask polling, results, packages) use the agent listener of the Manager under mutual TLS and are not part of this\nAPI.\n\nTypical flow:\n\n1. an administrator creates a bootstrap token for a cluster (see **Clusters**) and gives it to the install script of\n   the agent;\n2. the agent generates its private key and a certificate signing request (CSR), then calls\n   `POST /agent/v1/register` with the token, its names and its facts;\n3. the Manager checks the token (single cluster, expiring, limited number of uses), records the host, signs a\n   client certificate whose subject comes from the server (FQDN, hostname, IP, SPIFFE ID), never from the CSR, and\n   returns it with the agent secret and the CA;\n4. the agent then connects to the agent listener with that certificate.\n\nNo user permission is needed: the bootstrap token is the credential. Every registration, accepted or refused, is\naudited (`host.register`, or `host.reregister` for a known host)."
  },
  {
   "name": "agent-templates",
   "x-displayName": "Agent templates",
   "description": "The registry of the agent templates (Service Templates of the Navin products such as the Navin Enterprise RAG Agent): each template with its name, publisher, version, status and the catalog service that installs it. A template is `published` only when that service exists in the catalog and the template was published, by the release (status published) or on this Manager by an administrator (`POST .../publish`, the validation of the customer: the service definition joins the catalog of this Manager); otherwise `reason` says why it cannot be deployed and `publishable` whether it can be published here. Reading is open to any signed in user, like the stack catalog; publishing and withdrawing need `agent_templates:publish`."
  },
  {
   "name": "alerts",
   "x-displayName": "Alerts and notifications",
   "description": "Alerts raised by the Manager from its alert definitions (host down, disk full, service unhealthy, certificate\nabout to expire...), and the notification targets that receive them.\n\nAn alert is identified by a fingerprint (definition and target) and moves between the states `ok`, `warning`,\n`critical` and `unknown`; every change is kept in its history and notifies the enabled targets whose minimum\nseverity it reaches. A resolved alert has a `resolved_at`. Hosts in maintenance raise no alert.\n\nTypical flow:\n\n1. `GET /clusters/{cluster_id}/alerts` lists the open alerts; `POST /alerts/{alert_id}/ack` acknowledges one with\n   a note;\n2. `PATCH /alert-definitions/{definition_id}` tunes the thresholds and the interval of a definition;\n3. `POST /notification-targets` adds an email, webhook or syslog target, `POST .../test` sends a test message.\n\nWebhooks carry an `X-NM-Signature: t=<unix time>,v1=<hex HMAC-SHA256 of \"<t>.<body>\">` header when the target has\nan HMAC secret. Permissions: `alerts:read` to read, `alerts:manage` to acknowledge, tune and manage the targets."
  },
  {
   "name": "audit",
   "x-displayName": "Audit",
   "description": "The audit trail of the Manager: every change, sign in, refusal and sensitive read, with the actor (user, API\ntoken, agent or system), the action (for example `service.install`), the target, the cluster, the outcome\n(`success`, `failure`, `denied`), the client address and details. Events are chained: each one carries the hash of\nthe previous one, so a modified or deleted event breaks the chain.\n\nTypical flow:\n\n1. `GET /audit` with filters to investigate (newest first, paginated with `cursor`);\n2. `GET /audit/verify` to check that the chain is intact;\n3. `GET /audit/export` to hand the events to a SIEM or an auditor (NDJSON or CSV).\n\nPermission `audit:read` (global only; roles `admin`, `security_admin`, `auditor`). Verifications and exports are\nthemselves audited."
  },
  {
   "name": "auth",
   "x-displayName": "Authentication",
   "description": "Sign in and sign out of the console: identity providers, first run setup, local and LDAP login, second factor\n(TOTP), password change, session and OIDC login.\n\nSign in flow:\n\n1. `GET /auth/providers` lists the available methods (local, LDAP, OIDC providers) and tells whether the first\n   run setup is still required;\n2. `POST /auth/login` checks the username and password (local account or LDAP bind);\n3. when the second factor is required the answer is `{\"mfa_required\": true, \"mfa_token\": ...}`: send a TOTP code\n   or a recovery code to `POST /auth/mfa/verify`, or enroll first with `/auth/mfa/enroll/start` then\n   `/auth/mfa/enroll/confirm` when `enrollment_required` is true;\n4. when the password must be changed the API answers `403 password_expired` with a `password_change_token` in\n   `details`: send it with the new password to `POST /auth/password/change`, then sign in again;\n5. otherwise the session opens: the `nm_session` cookie is set and the answer gives the user, its effective\n   permissions, the `csrf_token` to send in `X-CSRF-Token` on unsafe requests, and `expires_at`.\n\nChecks of a login, in order: rate limits (address, username), first factor, lockout, disabled account, second\nfactor, password expiry. An unknown username takes the same time as a wrong password. Repeated failures lock the\naccount (`423 account_locked`) for the time of the security policy. Every outcome is audited (`auth.login`,\n`auth.mfa`, `auth.password_change`...). These endpoints need no permission; the self service MFA endpoints need a\nbrowser session (an API token is refused with `403 session_required`)."
  },
  {
   "name": "auth-config",
   "x-displayName": "Identity providers and security policy",
   "description": "Configuration of how users sign in: the LDAP directory, the OIDC providers and the security policy (passwords,\nlockout, session timeouts, roles that require MFA).\n\nSecrets (LDAP bind password, OIDC client secret) are sealed at rest and read back as\n`{\"secret\": true, \"set\": true|false}`. On a write, sending that object back (or leaving the field out) keeps the\nstored value, a string replaces it, an empty string clears it.\n\nTypical flow for LDAP:\n\n1. `PUT /auth-config/ldap` with the URLs, the bind account, the search bases and filters and the group to role\n   mappings;\n2. `POST /auth-config/ldap/test` with a test account to check the bind, the user search and the groups found;\n3. set `enabled` to true; users then sign in with `provider: \"ldap\"`.\n\nFor OIDC: `POST /auth-config/oidc` to add a provider (issuer, client id and secret, scopes, claims, mappings), then\n`POST /auth-config/oidc/{provider_id}/test` to check its discovery document and keys. The redirect URI to register\nat the provider is `<public URL>/api/v1/auth/oidc/{provider_id}/callback`.\n\nPermission `auth:manage` (global). Every change is audited (`auth_config.*`)."
  },
  {
   "name": "availability",
   "x-displayName": "High availability groups",
   "description": "A high availability group describes how one component of a cluster stays available: its HA mode (`single`,\n`active_passive`, `active_active`, `quorum`), its profile (`standalone`, `ha` with at least 2 replicas in 2 fault\ndomains, `critical-ha` with at least 3 in 3), its members and their fault domains, its failover policy and its\nrecovery objectives (RTO, RPO). The group reports its HA status from the heartbeats of its members.\n\nThe deployment mode tells what the Manager can prove: `SINGLE_HOST` (no HA promised), `NODE_GROUP` (failover\nproven on hosts), `K8S_EXISTING` and `K8S_MANAGED` (manifests validated offline), `MULTI_CLUSTER`,\n`EXTERNAL_MANAGED`. A `CLIENT_MANAGED` or `EXTERNAL_MANAGED` group is never started, stopped, upgraded, failed\nover or restored by the Manager.\n\nTypical flow:\n\n1. `GET /ha-modes` shows what each deployment mode supports;\n2. `POST /ha-groups` declares a group with its members;\n3. `POST /ha-groups/{group_id}/test-failover` runs a failover test under a lease with a fencing token;\n4. `GET /ha-groups/{group_id}/operations` shows the test runs with the observed RTO and RPO, the fencing\n   operations and the events.\n\nPermissions: `cluster:read` to read, `cluster:manage` to create a group, `services:operate` to test a failover.\nCritical operations fail closed: when the database or the audit write fails, the whole operation is refused."
  },
  {
   "name": "backup",
   "x-displayName": "Backup, restore and disaster recovery",
   "description": "The Backup & Recovery Manager: backup targets and plans, backup artefacts with their verifications, retention,\nrestore tests, restores and disaster recovery (sites, plans, exercises, failovers, DNS and load balancer\nswitches).\n\nBackup flow:\n\n1. `POST /backup-targets` declares where backups go (`s3`, `azure_blob`, `gcs`, `ibm_cos`, `seaweedfs` or\n   `filesystem`) with its capabilities;\n2. `POST /backup-plans` sets what is backed up, how often, the encryption key and the retention (an immutable\n   plan needs a target with object lock and retention);\n3. each backup is recorded with `POST /backup-plans/{plan_id}/backups`: the Manager hashes the file (SHA-256) and\n   sets its expiry; `POST /backups/{backup_id}/verify` checks the digest and the decryption, and\n   `POST /backups/{backup_id}/restore-tests` restores it in an isolated directory and signs the report.\n\nRestore flow (four eyes): `GET /restore-targets` lists the destinations declared by the operator, `POST\n/restores/plan` checks the compatibility and freezes the identity of one empty PostgreSQL destination, then two\napprovals by people other than the requester (`POST /restores/{plan_id}/approve`), an optional `dry-run`, and\n`execute`: the plan is marked `executing` before any write, the custom `pg_dump` is restored in one transaction\nby a restricted role, and the restored rows are read back and compared with the inventory recorded with the\nbackup. A failure is reported `failed`; nothing is rolled back automatically and a plan is never replayed.\n\nDisaster recovery: `POST /dr-plans` between two sites, then exercises or failover requests approved by another\nperson and completed with the RPO and RTO actually observed (nothing is estimated). DNS and load balancer changes\nare declared and evaluated, never applied by the Manager.\n\nPermissions (all global): `backup:read` to read, `backup:manage` for targets, plans, backups and tests,\n`restore:execute` for restores, `dr:manage` for disaster recovery. Every change is audited (`backup.*`,\n`restore.*`, `dr.*`)."
  },
  {
   "name": "blueprint",
   "x-displayName": "Blueprints",
   "description": "A blueprint describes the services of a cluster in a portable form, to rebuild the same platform on another\ncluster: the services with their mode, method, non secret configuration and bindings, and host groups (sets of\ncomponents that run together, with their number of hosts). Its shape:\n\n```json\n{\"schema\": \"navin-manager/blueprint/v1\", \"stack\": {\"name\": \"...\", \"version\": \"...\"},\n \"services\": [{\"name\": \"postgresql\", \"mode\": \"...\", \"method\": \"...\", \"managed\": true, \"config\": {}, \"bindings\": {}}],\n \"host_groups\": [{\"name\": \"host_group_1\", \"cardinality\": 3, \"components\": [{\"service\": \"postgresql\", \"component\": \"server\"}],\n                  \"hosts\": [\"<db1-host>\"]}]}\n```\n\nTypical flow:\n\n1. `GET /clusters/{source}/blueprint` exports a cluster (connected services are left out: they are endpoints of\n   one customer, not a portable part);\n2. `POST /clusters/{target}/blueprint/validate` with a `host_mapping` that maps each host group to hosts of the\n   target cluster;\n3. `POST /clusters/{target}/blueprint/apply` installs everything in one operation.\n\nPermission `cluster:manage` on the cluster; applying also needs `services:install`."
  },
  {
   "name": "clusters",
   "x-displayName": "Clusters",
   "description": "A cluster is an environment managed by the Navin Manager: a set of hosts (or a Kubernetes cluster) with its\nservices. It has a `mode` (`production`, `preprod`, `test`, `development`, `sandbox`) and an installation\n`profile` that sets the rules its operations must follow:\n\n- `development`: only the catalog must be valid;\n- `standard`: TLS on the Manager, client certificates for the agents, TLS on the services, MFA for administrators;\n- `banking-secure`: the strict rules plus the local mirror only, a remote audit copy, no sandbox service and the\n  approval of a second person for disruptive operations;\n- `air-gapped`: strict rules, mirror only, no outgoing traffic;\n- `hybrid`: standard rules plus TLS towards external services.\n\nWhile a rule of the profile fails, the operations that would install or start something are refused with\n`409 profile_blocked` (see **Lifecycle** for the evaluation of a profile).\n\nTypical flow:\n\n1. `POST /clusters` creates the cluster;\n2. `POST /clusters/{cluster_id}/bootstrap-tokens` creates a token and returns the commands that install and\n   register the agent on a host (or use the SSH bootstrap of **Hosts**);\n3. the hosts appear in `GET /clusters/{cluster_id}/hosts`; `GET /clusters/{cluster_id}/summary` and `/topology`\n   give the overview;\n4. install services (see **Services**).\n\nPermissions: `clusters:create` (global) to create, `cluster:read` to read, `cluster:manage` to change or delete,\n`hosts:manage` for the bootstrap tokens."
  },
  {
   "name": "configs",
   "x-displayName": "Configurations",
   "description": "The configuration of a managed service: its parameters (declared by the catalog with their types, defaults and\nsections), saved as numbered versions, with config groups that override values on some hosts.\n\nSaving a configuration does not touch the hosts: it creates a new version and marks the hosts whose rendered\nfiles would change as `stale_hosts`. Applying pushes the files and restarts the components.\n\nTypical flow:\n\n1. `GET .../config` reads the current values, the parameter definitions, the recommendations and the groups;\n2. `PUT .../config` saves the changed values as a new version (validated against the parameter definitions);\n3. `GET .../config/preview` shows the files a host would receive, `GET .../config/diff` compares two versions;\n4. `POST .../config/apply` starts the operation that writes the files and restarts the components (rolling by\n   default);\n5. `POST .../config/versions/{version}/restore` saves an old version again as the newest one.\n\nSecret parameters are read back as `{\"secret\": true, \"set\": true|false}`; sending that object back keeps the\nstored value, `null` removes a value. Permissions: `configs:read` to read, `configs:edit` to change and apply.\nChanges are audited (`config.*`, `config_group.*`)."
  },
  {
   "name": "connections",
   "x-displayName": "External connections",
   "description": "Connections to systems outside the clusters that services can use: databases (PostgreSQL, MySQL, ClickHouse),\nsearch engines (Elasticsearch, OpenSearch, Qdrant), messaging (Kafka, NATS, Redis), S3 object storage, LDAP and\nOIDC directories, SMTP, syslog and plain HTTP endpoints. A service binds to a connection through its `bindings`\n(kind `connection`).\n\nEach connection has a `type`, `params` checked against the parameters of that type, and one optional `secret`\n(password, token or key) sealed at rest and read back as `{\"secret\": true, \"set\": true|false, \"name\": ...}`.\n\nTypical flow:\n\n1. `POST /connections/validate` checks the parameters and runs the real protocol test with the secret, without\n   saving anything;\n2. `POST /connections` saves the connection;\n3. `POST /connections/{connection_id}/test` tests it again at any time and keeps the result in `last_test`.\n\nPermissions: `connections:read` to read, `connections:manage` to change and test (both global). Changes and\ntests are audited (`connection.*`); the secret is never returned nor audited."
  },
  {
   "name": "consoles",
   "x-displayName": "Service consoles",
   "description": "The local web interfaces of the installed services (for example the administration console of Keycloak or of a\nmessage broker), opened from the Manager.\n\nFor each console the Manager knows its internal address (published by an administrator, else the first quick link\nof the installed configuration) and evaluates the checks a bank requires: HTTPS, an internal DNS name,\nauthentication and no resource loaded from the Internet. On a production or pre-production cluster a console that\nfails a check cannot be opened. The consoles of identities and secrets (Keycloak, OpenBao, OpenFGA) are\nreserved to the vault administrators: the others see them locked, without their address.\n\nTypical flow:\n\n1. `GET /clusters/{cluster_id}/consoles` lists the consoles with their state and checks;\n2. `PUT .../consoles/{service}/access` publishes the internal address behind the HTTPS gateway and its protection;\n3. `POST .../consoles/{service}/open` returns the address to open (audited);\n4. `POST .../consoles/{service}/credentials/rotate` changes the password of the console account.\n\nPermissions: `services:operate` to list and open, `cluster:manage` to publish an address, `configs:edit` and\n`vault:manage` to rotate credentials."
  },
  {
   "name": "hosts",
   "x-displayName": "Hosts",
   "description": "The hosts of a cluster: machines registered by their Navin agent. A host has a `state` (`registering`, `healthy`,\n`unhealthy`, `lost`, `maintenance`, `decommissioned`), facts reported by the agent (operating system, CPU, memory,\ndisks, network), metrics, preflight checks, labels and kernel parameters, and the component instances placed on it.\n\nTypical flow:\n\n1. register hosts: with a bootstrap token of the cluster (see **Clusters**) and the install command run on each\n   host, or with `POST /clusters/{cluster_id}/hosts/ssh-bootstrap`, where the Manager connects over SSH and runs\n   the registration for you;\n2. `POST /hosts/{host_id}/preflight` then `GET /hosts/{host_id}/preflight` to check that a host is ready for the\n   services;\n3. `PATCH /hosts/{host_id}` sets the rack, labels, environment or maintenance mode;\n4. to retire a host, move its components away, then `POST /hosts/{host_id}/decommission`.\n\nPermissions: `cluster:read` to read, `hosts:manage` to change, globally or on the cluster of the host. Actions\non the host itself (preflight, facts, parameters, decommission, SSH bootstrap) start an operation and answer `202`\nwith its `operation_id`."
  },
  {
   "name": "hub",
   "x-displayName": "Navin Trusted Hub",
   "description": "Client of the Navin Trusted Hub: the Manager fetches (online) or imports (offline) the signed distribution\ndocument of the customer, verifies it, keeps its targets (approved packages and images with their digests) and\nfeeds the mirror with the approved images.\n\nBefore anything is stored the document is verified: Ed25519 signature by a pinned key, customer and Hub identity,\nexpiry, a version never lower than the stored one (and an equal version only with the same content) and SHA-256\ndigests. With `enforce` the installs only use images whose digest is an approved, non revoked target.\n\nTypical flow:\n\n1. `PUT /hub/settings` with the Hub URL, the customer, the pinned public keys and the access token;\n2. `POST /hub/sync` (online) or `POST /hub/import` with the document file (offline);\n3. `GET /hub` and `GET /hub/packages` show the state and the approved packages.\n\nPermissions: `system:read` to read, `settings:manage` to change, sync or import. Changes are audited (`hub.*`)."
  },
  {
   "name": "kubernetes",
   "x-displayName": "Kubernetes clusters",
   "description": "A cluster of the Manager can be a Kubernetes cluster instead of a set of hosts. The Manager talks to it through\nits API server only (never over SSH) with a sealed kubeconfig, and runs catalog services there as\n`ManagedComponent` resources of the group `platform.navin.ai`: it writes the desired state (server side apply,\nfield manager `navin-manager`), the Navin Platform Operator applies the charts, and every answer about a component\nis read from the status of its resource. The Navin Cluster Agent, deployed in the cluster, receives signed\ncommands and reports back.\n\nTypical flow:\n\n1. `GET .../kubernetes/import-rbac` gives the least privilege RBAC of the import identity (read the nodes,\n   namespaces, CRDs and classes; write only `platform.navin.ai` resources of the managed namespace);\n2. `POST /clusters/{cluster_id}/kubernetes` registers the API server and the kubeconfig of that identity;\n3. `POST .../kubernetes/discovery` reads the version, distribution, nodes, storage and ingress classes and add-ons;\n4. `POST .../kubernetes/components` installs a catalog service; `PATCH` and `/actions` configure, start, stop,\n   restart, scale or put it in maintenance;\n5. optionally, `GET .../kubernetes/agent/manifests` and `POST .../kubernetes/agent` deploy the cluster agent and\n   issue its identity, then `POST .../agent/commands` queues signed commands.\n\nThe kubeconfig is refused when it points at another API server, uses plain http, skips TLS verification, runs\nexec or auth provider plugins, references files, or uses proxies or impersonation. Permissions: `cluster:read`\nto read, `cluster:manage` to register and manage the agent, `hosts:manage` for the discovery, `services:install`\nto install and remove components, `configs:edit` to configure them, `services:operate` for actions and agent\ncommands. Every change is audited (`k8s.*`)."
  },
  {
   "name": "lifecycle",
   "x-displayName": "Lifecycle",
   "description": "The lifecycle of a cluster and of its services after the install: installation profile and approvals, preflight,\nliveness, readiness and smoke checks, upgrades with rollback and restore, coordinated backups and restores, drift\ndetection, sanitized support bundles, signed acceptance reports and the uniform component sheet.\n\nTypical flows:\n\n1. **Profile**: `GET /profiles` lists the profiles, `GET /clusters/{cluster_id}/profile` evaluates the rules of\n   the cluster profile against the real state (a failed rule blocks installs and starts), `PUT` changes it.\n2. **Approvals** (`banking-secure`): `POST .../approvals` requests one for a disruptive action, another user\n   decides it with `POST .../approvals/{approval_id}/decision`, then the action uses it (send its `approval_id`\n   or let the Manager find it).\n3. **Upgrade**: `GET .../services/{service}/upgrade` shows whether the catalog release is reachable, then\n   `POST` runs it: preflight, backup of a stateful service, canary host, the other hosts one at a time, checks.\n   `POST .../upgrades/{upgrade_id}/rollback` goes back to the previous release, `.../restore` restores the backup\n   taken before it.\n4. **Backup**: `POST .../backups` takes a coordinated backup of several services; `.../backups/{backup_id}/restore`\n   restores one.\n5. **Drift**: `POST .../drift/scan` compares the files and units on the hosts with what the Manager wrote,\n   `GET .../drift` lists the findings, `POST .../drift/{finding_id}/reconcile` rewrites them.\n6. **Acceptance**: `POST .../acceptance-reports` runs every check and produces a report signed with Ed25519,\n   readable in JSON or HTML and verifiable offline.\n\nPermissions: `cluster:read` to read, `cluster:manage` for the profile, approval decisions and support bundles,\n`services:install` for preflight, upgrades, restores and acceptance, `services:operate` to request approvals,\ntake backups and scan drift, `configs:edit` to reconcile a drift."
  },
  {
   "name": "mcp",
   "x-displayName": "MCP servers",
   "description": "The MCP (Model Context Protocol) servers of a tenant project: created from a preset of the Navin library or typed\nby an administrator, tested, and optionally hosted on the `mcp-host` service of a cluster.\n\nRules:\n\n- every route takes `tenant` and `project`; a server of another tenant or project answers `404\n  mcp_server_not_found`, and no route lists the servers of every tenant;\n- the secret fields of a preset, the HTTP headers and the environment of a custom server are sealed with the\n  master key; responses and audit events name the configured fields only (`configured_fields`, `secret_fields`,\n  `has_secrets`), never a value;\n- users never reach an MCP server on the internet: a URL must name a private IP address (RFC 1918, IPv6 ULA) or a\n  host of the setting `mcp_internal_hosts`; loopback, link local and cloud metadata addresses are always refused\n  (`422 mcp_online_forbidden`).\n\nTypical flow:\n\n1. `GET /mcp/presets` lists the presets and the fields to fill;\n2. `POST /mcp/servers` creates a server from a preset (`preset` and `values`) or a custom one (`url` for streamable\n   HTTP or SSE, `command` for stdio);\n3. `POST /mcp/servers/{server_id}/test` speaks MCP to it and lists its tools;\n4. for a stdio server, `POST /mcp/servers/{server_id}/hosting` hosts it on a cluster: it gets a URL\n   `/t/{tenant}/p/{project}/s/{name}/mcp` on the instance and a bearer token.\n\nPermissions (global): `mcp:read` to read, `mcp:manage` to change, test and host, `mcp:publish` (admin role only)\nto read the hosted servers with their tokens. Changes are audited (`mcp.*`)."
  },
  {
   "name": "mcp-runtime",
   "x-displayName": "MCP runtime",
   "description": "The MCP runtime of a Kubernetes cluster: the ToolHive Kubernetes Operator, installed from pinned charts, and the\nephemeral MCP server instances the lifecycle controller of the Control Plane creates in it.\n\nOnly `MCPServer` objects labelled `app.kubernetes.io/managed-by=eai-mcp-runtime` in a project namespace\n`mcp-<12 hex>` labelled `eai.io/mcp-runtime=true` are listed, deleted or restarted; any other object answers\n`404 mcp_runtime_instance_not_found`, exactly like a missing one, and the refusal is audited.\n\nTypical flow: `POST .../mcp-runtime/install` once, then `GET .../mcp-runtime` to follow the operator and the\ninstances; `restart` or delete an instance when needed. Permissions: `cluster:read` to read, `services:install`\nto install, `services:operate` to restart or delete an instance."
  },
  {
   "name": "me",
   "x-displayName": "My profile",
   "description": "The profile of the signed in user and its personal API tokens.\n\nAn API token lets a script call the API as you: `Authorization: Bearer nmt_<12 hex>_<secret>`. It is shown once\nat creation and stored as a hash. It may be restricted to a list of permissions, each one you must hold (globally\nor on a cluster); a token never grants more than you hold at the time of the call, and it stops working when your\naccount is disabled.\n\nTypical flow:\n\n1. sign in to the console (tokens are created and revoked from a browser session only: a token cannot mint another\n   one);\n2. `POST /me/tokens` with a name, an optional permission list and a lifetime, then keep the `token` of the answer;\n3. `GET /me/tokens` shows the prefix, the expiry and the last use of each token;\n4. `DELETE /me/tokens/{token_id}` revokes a token at once.\n\nNo permission is needed: every authenticated user manages its own profile and tokens. Changes are audited\n(`user.profile_update`, `token.create`, `token.revoke`)."
  },
  {
   "name": "meta",
   "x-displayName": "Version",
   "description": "Public metadata of the Manager. No authentication is needed."
  },
  {
   "name": "mirror",
   "x-displayName": "Local mirror",
   "description": "The local mirror holds the packages, container images and Python wheels the agents install from, so that a site\nwithout Internet access (or under the `banking-secure` and `air-gapped` profiles) never downloads from outside.\nIt is filled from an offline bundle described by a manifest.\n\nTypical flow: copy the bundle to the mirror directory, `POST /mirror/reload` (with `verify=true` to check the\ndigests), then `GET /mirror` to see what is loaded and what the catalog still misses.\n\nPermissions: `system:read` to read, `settings:manage` to reload."
  },
  {
   "name": "navin-sm",
   "x-displayName": "Navin SM",
   "description": "Navin SM is the Navin desktop and CLI build an organization gives to its staff, with a file that points Navin at\nthe organization's own LiteLLM proxy and models (Azure, Bedrock, vLLM... behind LiteLLM), optionally exclusive (no\nother provider allowed). A profile is that file: the organization, the gateway (base URL, authentication,\nheaders, CA bundle, models, default model, routes, exclusive flag) and the managed policy Navin enforces\n(permissions, MCP allowlist, plugins, hooks, bypass, pinned environment).\n\n`GET /navin-sm/profiles/{profile_id}/export` returns the `managed-settings.json` of the contract (organization\ngateway, version 1), checked against `catalog/schema/navin-sm-managed-settings.schema.json`. The IT department\ndeploys it to `/etc/navin/managed-settings.json` (Linux), `/Library/Application Support/Navin/managed-settings.json`\n(macOS) or `%ProgramData%\\Navin\\managed-settings.json` (Windows); a user can also import it in Navin Settings >\nOrganization > Import (only `organization` and `gateway` are then applied).\n\nThe shared key of a `shared_key` gateway is a vault entry reference (`shared_key_ref`), never stored with the\nprofile: it is unsealed only to call the proxy or to write the exported file. Using one also needs\n`vault:manage`. Permission `settings:manage` (global). Every change, export and discovery is audited\n(`navin_sm.*`), refusals included, never with a key.\n\nA profile linked to a LiteLLM service installed by the Manager (`litellm_cluster_id`, `litellm_service`) is\ndiscovered with the master key of the service, kept in the server, and issues the LiteLLM virtual keys of the\nstaff (`/navin-sm/profiles/{profile_id}/keys`, permission `navin_sm:keys`, audit `navin_sm.key.*`): a key is\nshown once, the Manager keeps its alias and sha256 only. The tracking (`/usage`) reads `/key/info` and\n`/spend/logs` of the proxy through the server and says so when the proxy is out of reach. The distribution\n(`/navin-sm/distribution`, catalog service `navin-sm`, delivery `distribute`) keeps the packages of the release,\neach verified against its published SHA256, and the bundle (`/bundle?os=`) packs the file, the CA of the Manager\nand the deployment scripts of one system."
  },
  {
   "name": "network",
   "x-displayName": "Network flows",
   "description": "The network flows of a cluster, computed from what the Manager knows, for the network team that opens them in its\nsecurity groups or host firewalls. Each flow belongs to a scope:\n\n- `platform`: users to the console of the Manager, every host to the agent API and the registration listener, the\n  Manager to the hosts on TCP 22 for the SSH bootstrap, the hosts to an external mirror or registry;\n- `service`: consumers of a binding to their provider, Prometheus to the metrics endpoints, clients to the public\n  endpoints;\n- `intra_service`: between the hosts of one service (transport, peers, gossip, replication ports);\n- `egress`: consumers of a connected service or of an external connection to its endpoint, and the Manager to the\n  health URL of a connected service.\n\nTypical flow: `GET .../network/flows` (JSON or CSV) to review the matrix, then `GET .../network/rules` for the\ncommands that open it on a cloud provider or a host firewall. Read only; permission `cluster:read`."
  },
  {
   "name": "node-security",
   "x-displayName": "Node security",
   "description": "The security of the managed hosts and of their node agents: inventory, SSH policy, preflight and SSH bootstrap\nof the agent, enrollment tokens bound to the agent key, trust state (quarantine, revocation, recovery),\nmanagement mode, signed agent commands and their receipts, agent update and SSH break glass.\n\nBootstrap flow:\n\n1. `PUT /clusters/{cluster_id}/ssh-policy` sets the accepted keys (Ed25519, or RSA of at least `rsa_min_bits`),\n   the approved user CAs, the bootstrap account and the certificate rotation;\n2. `POST /hosts/preflight` reads the host over SSH (strict host key checking) and from the Manager (DNS, TCP) and\n   returns checks graded `pass`, `warning` or `blocking`;\n3. `POST /hosts/bootstrap/plan` shows the plan (sudo allowlist, systemd unit), then `POST /hosts/bootstrap` runs\n   it: the signed agent binary is verified, a temporary key is used and removed at the end, a failing step rolls\n   back;\n4. or `POST /hosts/enroll` issues a single use token bound to the fingerprint of the agent key, for an agent\n   installed by other means.\n\nDay to day: `POST /hosts/{host_id}/commands` sends a command signed with Ed25519 (the agent checks signature,\ntarget, expiry, nonce and scope) and `GET .../receipts` reads the results; `quarantine`, `revoke` and `recover`\nchange the trust state; break glass gives an emergency OpenSSH certificate after two approvals.\n\nPermissions: `cluster:read` on the cluster of the host to read, `hosts:manage` to change. Private keys are only\naccepted in the request body and kept in memory for the run, never stored nor logged; a body with a password\nfield is refused. Every change and every refusal is audited."
  },
  {
   "name": "operations",
   "x-displayName": "Operations",
   "description": "An operation is the unit of every change the Manager makes: an install, a restart, an upgrade, a backup, a host\nbootstrap... It is made of ordered stages; each stage holds tasks, usually one per host, run by the Navin agents.\nStatus of an operation: `pending`, `running`, `succeeded`, `failed` or `aborted`; `progress` goes from 0 to 100.\n\nTypical flow:\n\n1. an endpoint that changes something answers `{\"operation_id\": ...}`;\n2. `GET /operations/{operation_id}` returns the operation with its stages and tasks; poll it until the status is\n   final;\n3. `GET /operations/{operation_id}/tasks/{task_id}/logs` reads the output of a task, page after page with\n   `after_seq`;\n4. `POST /operations/{operation_id}/abort` stops a running operation; `POST /operations/{operation_id}/retry`\n   creates a new operation from a failed or aborted one.\n\nPermissions: `operations:read` to read, `operations:abort` to abort or retry, globally or on the cluster of the\noperation."
  },
  {
   "name": "pki",
   "x-displayName": "PKI and certificates",
   "description": "The certificate authority of the Manager and the certificates it issues: client certificates of the agents and\nTLS certificates of the service components.\n\nTypical flow: `GET /pki/ca` to get the CA and pin its SHA-256 fingerprint, `GET /clusters/{cluster_id}/certificates`\nto see what expires, `POST /clusters/{cluster_id}/certificates/rotate` to issue new service certificates and\nrestart the components with them. Permissions: any signed in user reads the CA, `cluster:read` lists the\ncertificates, `pki:manage` (global) rotates them."
  },
  {
   "name": "services",
   "x-displayName": "Services",
   "description": "The services of a cluster: catalog services (PostgreSQL, Keycloak, Kafka...) installed and run by the Manager on\nthe hosts, or existing services of your own registered with **Configure & Connect** (never installed, started or\nstopped by the Manager). A managed service is made of components (for example `server`, `replica`) placed on\nhosts; each placement is a component instance with its state and health.\n\nInstall flow:\n\n1. `POST /clusters/{cluster_id}/services/validate` with the services, their placements and configuration: returns\n   the errors, the high availability checks, the dependencies that would be added and the plan (order, stages,\n   steps); nothing is changed;\n2. `POST /clusters/{cluster_id}/services` with the same body: creates the install operation and returns its\n   `operation_id`;\n3. follow it with `GET /operations/{operation_id}` (see **Operations**);\n4. run it day to day with `/actions` (start, stop, restart, rolling restart, checks), `/commands/{command}`,\n   `/components` and `/mode`.\n\nGates applied when an operation is created: the profile of the cluster (`409 profile_blocked`), the\nadministrative state of the service (`409 service_admin_state`), the security lock of the cluster\n(`423 cluster_security_locked`), high availability (`409 ha_requirements_not_met` or\n`ha_acknowledgement_required`, unless acknowledged) and, under `banking-secure`, the approval of a second person\nfor a disruptive action (`409 approval_required`).\n\nPermissions: `cluster:read` to read, `services:install` to install, connect, uninstall, change components or\nreinstall, `services:operate` to run actions, commands, modes and logs, `configs:read` for the client\nconfiguration, `pki:manage` for the security suspension and the security lock. Every change is audited."
  },
  {
   "name": "settings",
   "x-displayName": "Settings",
   "description": "General settings of the Manager: site name, default language, install defaults (preferred method, registry,\nmirror), SMTP and remote syslog for the alert notifications (syslog also serves the remote audit rule of `banking-secure`), data retention and the corporate proxy of the\nmanaged hosts. Every signed in user reads the non secret values; `settings:manage` (global) writes them. The SMTP\npassword is read back as `{\"secret\": true, \"set\": true|false}`. Changes are audited (`settings.update`)."
  },
  {
   "name": "stack",
   "x-displayName": "Stack catalog",
   "description": "The catalog of services the Manager can install (the stack): every service with its versions, components, install methods, parameters, dependencies and high availability rules. Any signed in user can read it; no permission is needed."
  },
  {
   "name": "system",
   "x-displayName": "System",
   "description": "Self monitoring of the Manager: health of the database, the engine, the agents and the scheduled jobs, the list of supported operating systems and the Prometheus service discovery of a cluster. Permissions: `system:read` for the health, `cluster:read` for the service discovery; the supported systems are open to every signed in user."
  },
  {
   "name": "telemetry",
   "x-displayName": "Telemetry",
   "description": "State of the real time export of the metrics and events of the Manager to ClickHouse. The platform ships no dashboard server (ADR-0169): machines and services are followed in the Manager itself and the exported tables are read with SQL. The export is off while no ClickHouse URL is configured. Any principal that reads at least one cluster (`cluster:read`, global or on a cluster)."
  },
  {
   "name": "users",
   "x-displayName": "Users and roles",
   "description": "Administration of the console accounts and of their role bindings.\n\nA user is `local` (password stored by the Manager), `ldap` or `oidc` (created at its first sign in). A role\nbinding is a role (`admin`, `security_admin`, `cluster_admin`, `operator`, `viewer`, `auditor`) given globally or on\none cluster; `admin`, `security_admin` and `auditor` are global only. Bindings set here are `manual`; the ones\nmapped from LDAP or OIDC groups are renewed at each sign in and kept when the manual ones are replaced.\n\nTypical flow:\n\n1. `GET /roles` lists the roles with their permissions and scopes;\n2. `POST /users` creates a local account with its first bindings (the password must be changed at the first sign\n   in by default);\n3. `PUT /users/{user_id}/roles` replaces its manual bindings; `PATCH /users/{user_id}` disables it;\n4. `POST /users/{user_id}/unlock`, `/password` and `/mfa/reset` help a user who is locked out.\n\nGuards: the last active administrator (enabled user with a global `admin` binding) can never be deleted, disabled\nor demoted (`409 last_admin`); only a full administrator can grant `admin` or act on an administrator account\n(`403 user_manage_denied`); you cannot disable or delete yourself. Permissions: `users:read` to read, `users:manage`\nto change. Every change and refusal is audited (`user.*`)."
  },
  {
   "name": "vault",
   "x-displayName": "Vault",
   "description": "The vault of the platform administrators: the credentials of the platform services. An entry is a service name,\nits URL, a login, a password and an API key or secret key. Only the name is stored in clear; URL, login, password\nand key are one document sealed with AES-256-GCM and the master key. Lists and sheets never carry the password nor\nthe key (`has_password`, `has_api_key`); `POST .../reveal` returns them and is audited, the audit keeping the\nservice name only, never a value.\n\nEntries of the installed services (`managed`) are created and refreshed by the Manager after every successful\ninstall or configuration apply, with the credentials generated for that install; `POST /vault/import` refreshes\nthe services installed before. A field changed by hand is kept by the refresh. The login, password and key of a\nconsole whose credentials the Manager rotates only change through\n`POST /clusters/{cluster_id}/consoles/{service}/credentials/rotate` (see **Service consoles**).\n\nPermission `vault:manage` (global). Every change and every reveal is audited (`vault.*`)."
  }
 ],
 "x-tagGroups": [
  {
   "name": "Access",
   "tags": [
    "auth",
    "me",
    "users",
    "auth-config"
   ]
  },
  {
   "name": "Clusters and hosts",
   "tags": [
    "clusters",
    "hosts",
    "agent",
    "network",
    "settings"
   ]
  },
  {
   "name": "Services",
   "tags": [
    "services",
    "configs",
    "connections",
    "consoles",
    "blueprint",
    "hub",
    "stack"
   ]
  },
  {
   "name": "Operations",
   "tags": [
    "operations",
    "alerts",
    "availability",
    "telemetry",
    "audit"
   ]
  },
  {
   "name": "Security",
   "tags": [
    "pki",
    "vault",
    "node-security"
   ]
  },
  {
   "name": "Backup and lifecycle",
   "tags": [
    "backup",
    "lifecycle",
    "mirror"
   ]
  },
  {
   "name": "Kubernetes and MCP",
   "tags": [
    "kubernetes",
    "mcp",
    "mcp-runtime"
   ]
  },
  {
   "name": "System",
   "tags": [
    "system",
    "meta"
   ]
  },
  {
   "name": "Other",
   "tags": [
    "agent-templates",
    "navin-sm"
   ]
  }
 ]
}
