{
  "openapi": "3.0.4",
  "info": {
    "title": "Voltage Park Cloud API",
    "version": "1.0.0",
    "description": "Bare metal GPU fleet provisioning and management.",
    "contact": {
      "name": "Voltage Park Customer Support"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
    }
  },
  "servers": [
    {
      "url": "https://api.sea1.voltagepark.com",
      "description": "Seattle (sea1)"
    },
    {
      "url": "https://api.iad1.voltagepark.com",
      "description": "Washington D.C. (iad1)"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/v1/audit-logs": {
      "get": {
        "operationId": "getAuditLogs",
        "summary": "List recent audit logs for your organization",
        "description": "Returns the most recent audit events for the authenticated caller's organization \u2014 who did what, when, and from where. Scoped automatically to your organization (derived from your token); you cannot query another organization's activity.\n\n**When to use:**\n- Let an organization owner review what users in their org have been doing\n- Investigate recent access or changes across your fleets\n\n**Scope & limits:**\n- Returns up to the 2000 most recent events, newest first.\n- Covers roughly the last 36 hours of activity. Older activity is available through the 90-day archive export.\n- No filtering or pagination yet.\n\n**Note:** Actions taken by Voltage Park support/admin staff are attributed to their own organization and are not included here.",
        "tags": [
          "Audit"
        ],
        "responses": {
          "200": {
            "description": "The most recent audit events for your organization (up to 2000, newest first). Returns an empty list when there is no recent activity.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthenticated - missing or invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error before the audit query could run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The upstream audit log store failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/audit-logs/export": {
      "post": {
        "operationId": "startAuditLogExport",
        "summary": "Start building the 90-day audit log export for your organization",
        "description": "Starts preparing a downloadable archive of your organization's audit events for the trailing 90 days, and returns immediately \u2014 building it takes longer than a request can wait. Poll `GET /v1/audit-logs/export` until `status` is `ready`, then download the `url` it returns. Scoped automatically to your organization (derived from your token); you cannot export another organization's activity.\n\n**When to use:**\n- Produce 90 days of audit evidence for a SOC 2 or customer security review\n- Retain or analyze activity beyond the recent-events endpoint's bounded preview\n\n**Window:** whole days only. The archive covers the 90 days ending at the most recent UTC midnight, so the current partial day is excluded and every caller on the same UTC day gets the identical archive. There are no parameters \u2014 the window is fixed, which is what makes the archive reusable.\n\n**Idempotent:** safe to call repeatedly. If today's archive is already built this returns `ready` without doing any work; if a build is already running it returns `running` rather than starting a second one. At most one archive is built per organization per UTC day.\n\n**Expect a wait** on the first call of a UTC day \u2014 typically under a minute, and longer for organizations with high activity. Subsequent calls the same day are immediate.",
        "tags": [
          "Audit"
        ],
        "responses": {
          "202": {
            "description": "Accepted. The response carries the current status: `running` when this call started the build (or found one already in progress), or `ready` when today's archive already existed and no work was needed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogExportStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthenticated - missing or invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated but not permitted to export audit logs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error before the export could be started (for example, audit export is not configured for this deployment)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "An upstream dependency failed while starting the export (object storage was unreachable)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "get": {
        "operationId": "getAuditLogExport",
        "summary": "Check the 90-day audit log export and get its download URL",
        "description": "Reports the state of your organization's 90-day audit export and, once it is `ready`, returns a short-lived presigned download URL. Start an export with `POST /v1/audit-logs/export` first; this endpoint only reports and never starts one, so it is safe to poll.\n\n**Statuses:**\n- `notStarted` \u2014 no archive exists for today's window and no build is running. Call `POST` to start one.\n- `running` \u2014 a build is in progress. Poll again in a few seconds.\n- `ready` \u2014 the archive is complete; `url` and `expiresAt` are present.\n- `failed` \u2014 the build did not finish; `error` carries a short reason. Call `POST` to try again.\n\n**Format:** gzip-compressed NDJSON (`.ndjson.gz`) \u2014 one audit event per line, oldest first.\n\n**Note:** the returned `url` expires within minutes \u2014 download promptly, and call this endpoint again for a fresh URL if it lapses. The archive itself persists for the rest of the UTC day. Actions taken by Voltage Park support/admin staff are attributed to their own organization and are not included here.",
        "tags": [
          "Audit"
        ],
        "responses": {
          "200": {
            "description": "The current state of your organization's 90-day export, including a presigned download URL when it is ready.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogExportStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthenticated - missing or invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated but not permitted to export audit logs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error before the status could be read (for example, audit export is not configured for this deployment)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "An upstream dependency failed while reading the export status or minting the download URL (object storage was unreachable)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets": {
      "get": {
        "operationId": "listFleets",
        "summary": "List your fleets",
        "description": "Get all GPU fleets in your organization. Each fleet represents a cluster of GPU nodes ready for your workloads.\n\n**When to use:**\n- Display fleets in your dashboard\n- Check which fleets are currently active\n- Get an overview of your GPU infrastructure\n\n**Response Format:** Always returns ListFleetsResponse with `fleets` array, `limit`, and `nextToken` fields.\n\n**Pagination:** Optional - add `limit` parameter to paginate. Without `limit`, returns all fleets with `limit: null` and `nextToken: null`.",
        "tags": [
          "Fleets"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            },
            "description": "Optional: Maximum number of fleets to return per page (0-100). Use 0 to get all results in paginated format. If provided, response includes pagination metadata."
          },
          {
            "name": "nextToken",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional: Pagination token from previous response to retrieve the next page. Only valid when 'limit' is provided."
          }
        ],
        "responses": {
          "200": {
            "description": "List of fleets retrieved successfully. Always returns ListFleetsResponse with unified format. When pagination not used, limit and nextToken are null.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListFleetsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid pagination parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fleets/{fleetId}": {
      "get": {
        "operationId": "getFleet",
        "summary": "Get fleet details",
        "description": "Get complete information about a specific fleet, including configuration, status, and current node count.\n\n**When to use:**\n- Display fleet details in your application\n- Check current fleet configuration before scaling\n- Monitor fleet status and health\n\n**Response includes:** GPU type, node count, region, networking, storage, and current operational status.",
        "tags": [
          "Fleets"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier",
            "example": "900e8eac-2b1f-421f-a635-72556268b41f"
          }
        ],
        "responses": {
          "200": {
            "description": "Success - returns complete fleet information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fleet"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fleets/{fleetId}/services/grafana": {
      "get": {
        "operationId": "getFleetGrafanaDashboards",
        "summary": "Get Grafana dashboards for a specific fleet",
        "description": "Returns monitoring dashboards for a specific fleet. Each fleet can have multiple dashboards for different purposes (overview, detailed metrics, GPU performance, etc.).\n\n**When to use:**\n- Display available dashboards in your fleet detail view\n- Show monitoring options to your users\n- Embed dashboards in your application\n\n**Important notes:**\n- Empty array means no monitoring is configured for this fleet\n- Users authenticate with Auth0 SSO when clicking dashboard links\n- Dashboards automatically reflect current fleet state",
        "tags": [
          "Monitoring"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier",
            "example": "900e8eac-2b1f-421f-a635-72556268b41f"
          }
        ],
        "responses": {
          "200": {
            "description": "Success - returns array of available dashboards (empty if monitoring not configured)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GrafanaDashboardResponse"
                  }
                },
                "example": [
                  {
                    "fleetId": "900e8eac-2b1f-421f-a635-72556268b41f",
                    "dashboardId": "overview",
                    "dashboardUrl": "https://grafana.sea1.voltagepark.com/d/abc123",
                    "available": true
                  }
                ]
              }
            }
          },
          "404": {
            "description": "Fleet not found - check that the fleet ID is correct and belongs to your organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fleets/{fleetId}/health": {
      "get": {
        "operationId": "getFleetHealth",
        "summary": "Get fleet health metrics",
        "description": "Get detailed health information about fleet nodes, including connectivity and operational status. Only available for ACTIVE fleets with nodes.\n\n**When to use:**\n- Check if nodes are healthy before running workloads\n- Diagnose connectivity or performance issues\n- Monitor fleet operational health\n\n**Note:** Returns 422 if fleet is not active or has no nodes yet.",
        "tags": [
          "Fleets"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier",
            "example": "900e8eac-2b1f-421f-a635-72556268b41f"
          }
        ],
        "responses": {
          "200": {
            "description": "Success - returns health metrics for all nodes in the fleet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FleetHealthResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Fleet is not in ACTIVE status or has inconsistent state (ACTIVE fleet with no nodes)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error message describing why health cannot be retrieved"
                    },
                    "fleetId": {
                      "type": "string",
                      "description": "Unique identifier for the fleet"
                    },
                    "status": {
                      "type": "string",
                      "description": "Current fleet status"
                    }
                  },
                  "required": [
                    "error",
                    "fleetId",
                    "status"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fleets/{fleetId}/kubernetes-v2/kubeconfig": {
      "get": {
        "operationId": "getCustomerMks2Kubeconfig",
        "summary": "Download customer managed Kubernetes kubeconfig",
        "description": "Returns a customer-role kubeconfig for the managed Kubernetes cluster bound to the fleet. The credential is time-limited; clients should refetch before expiresAt. Org-scoped: the caller's JWT org must own the fleet.",
        "tags": [
          "Kubernetes"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Success - returns a customer-role kubeconfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KubeconfigV2Response"
                }
              }
            }
          },
          "400": {
            "description": "Fleet exists but is not Kubernetes-backed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found in caller's org",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "The Kubernetes control plane error or internal failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/kubernetes-v2/health": {
      "get": {
        "operationId": "getCustomerMks2ClusterHealth",
        "summary": "Get managed Kubernetes cluster health",
        "description": "Returns the current health status of the managed Kubernetes cluster bound to the fleet: top-level health, control-plane component health, per-worker-node health, networking (Cilium) health, and API-server-to-worker connectivity status. Org-scoped: the caller's JWT org must own the fleet. Reads are live (not cached). Returns 404 when the cluster has no health snapshot yet, 502 when the health service reports a server error, and 500 when the health service cannot be reached.",
        "tags": [
          "Kubernetes"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Success - returns cluster health",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Mks2ClusterHealth"
                }
              }
            }
          },
          "400": {
            "description": "Fleet exists but is not Kubernetes-backed, or the Kubernetes control plane rejected the request as malformed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found in caller's org, or the Kubernetes control plane has no health snapshot for the cluster yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call (network unreachable, configuration, etc.)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The Kubernetes control plane returned 5xx",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/kubernetes-v2/nodes/{nodeId}": {
      "get": {
        "operationId": "getCustomerMks2WorkerNode",
        "summary": "Get managed Kubernetes worker node detail",
        "description": "Returns the full detail for a single worker node in the fleet's managed Kubernetes cluster, including Kubernetes conditions, GPU info, labels/annotations, and registration timestamps. Org-scoped: the caller's JWT org must own the fleet. Unlike the list endpoint (joined-only), this resolves registered-but-not-yet-joined nodes by id.",
        "tags": [
          "Kubernetes"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Managed Kubernetes worker-node identifier (registry id)"
          }
        ],
        "responses": {
          "200": {
            "description": "Success - returns the worker-node detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Mks2WorkerNodeDetail"
                }
              }
            }
          },
          "400": {
            "description": "Fleet exists but is not Kubernetes-backed, or the Kubernetes control plane rejected the request as malformed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found in caller's org, or the Kubernetes control plane has no cluster / no such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call (network unreachable, configuration, etc.)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The Kubernetes control plane returned 5xx",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/kubernetes-v2/nodes/{nodeId}/cordon": {
      "post": {
        "operationId": "cordonCustomerMks2WorkerNode",
        "summary": "Cordon a managed Kubernetes worker node",
        "description": "Marks the node unschedulable so the scheduler stops placing new pods on it. Existing pods are left running (use drain to evict them). Org-scoped: the caller's JWT org must own the fleet. The node must be joined to the cluster; otherwise the request is rejected with 400. Idempotency: pass `Idempotency-Key` to make this safely retryable.",
        "tags": [
          "Kubernetes"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Managed Kubernetes worker-node identifier (registry id)"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Node cordoned (marked unschedulable)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Mks2CordonNodeResponse"
                }
              }
            }
          },
          "400": {
            "description": "Fleet exists but is not Kubernetes-backed, the node id is not a member of the fleet's bare-metal list, or the Kubernetes control plane rejected the request (e.g. the node has not joined the cluster yet)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found in caller's org, or the Kubernetes control plane has no cluster / no such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The Kubernetes control plane returned 5xx",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/kubernetes-v2/nodes/{nodeId}/uncordon": {
      "post": {
        "operationId": "uncordonCustomerMks2WorkerNode",
        "summary": "Uncordon a managed Kubernetes worker node",
        "description": "Marks the node schedulable again (reverses cordon), allowing the scheduler to place new pods on it. Org-scoped: the caller's JWT org must own the fleet. The node must be joined to the cluster; otherwise the request is rejected with 400. Idempotency: pass `Idempotency-Key` to make this safely retryable.",
        "tags": [
          "Kubernetes"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Managed Kubernetes worker-node identifier (registry id)"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Node uncordoned (marked schedulable)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Mks2CordonNodeResponse"
                }
              }
            }
          },
          "400": {
            "description": "Fleet exists but is not Kubernetes-backed, the node id is not a member of the fleet's bare-metal list, or the Kubernetes control plane rejected the request (e.g. the node has not joined the cluster yet)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found in caller's org, or the Kubernetes control plane has no cluster / no such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The Kubernetes control plane returned 5xx",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/kubernetes-v2/nodes/{nodeId}/drain": {
      "post": {
        "operationId": "drainCustomerMks2WorkerNode",
        "summary": "Drain a managed Kubernetes worker node",
        "description": "Cordons the node and then evicts its pods (respecting PodDisruptionBudgets). Org-scoped: the caller's JWT org must own the fleet. The node must be joined to the cluster; otherwise the request is rejected with 400, or 409 if the cluster is currently restoring or deleting. The request body is optional; omit it to use the defaults. Idempotency: pass `Idempotency-Key` to make this safely retryable.",
        "tags": [
          "Kubernetes"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Managed Kubernetes worker-node identifier (registry id)"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Mks2DrainNodeRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Drain initiated (pods evicted)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Mks2DrainNodeResponse"
                }
              }
            }
          },
          "400": {
            "description": "Fleet does not have a Kubernetes cluster, the node is not a member of the fleet, the request body is malformed, or the node has not joined the cluster",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found in the caller's org, or the cluster or node was not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "The cluster is currently restoring or deleting",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/cluster-validation": {
      "get": {
        "operationId": "listClusterValidations",
        "summary": "List recent cluster validation runs",
        "description": "Returns up to the 10 most recent cluster-validation runs for your fleet, newest first.",
        "tags": [
          "Cluster Validation"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Recent cluster-validation runs (max 10, newest first).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClusterValidationListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Fleet does not support cluster validation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "triggerClusterValidation",
        "summary": "Start a cluster validation run",
        "description": "Starts a cluster-validation run against your fleet's nodes and returns the run id (use it to poll status, view details, or fetch the report). Runs are always multi-host. An optional node subset and an optional list of tests (from the test catalog) are honored; omit the tests to run the default set. Kubernetes-aware runs require a Kubernetes-enabled fleet; the required cluster credential is obtained automatically.",
        "tags": [
          "Cluster Validation"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerTriggerClusterValidationRequest"
              }
            }
          },
          "description": "Optional run parameters. Omit the body to validate all fleet nodes with the default set of tests."
        },
        "responses": {
          "202": {
            "description": "Validation run accepted and started.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClusterValidationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Fleet does not support cluster validation, or the request is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A cluster validation is already running for this fleet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "412": {
            "description": "GPU validation has not finished on one or more of the target nodes, so the run cannot start. The message names each node and its state. Retry once validation has finished on those nodes, or leave them out of the run with `nodeNames`. If a node failed GPU validation or stays blocked, contact support.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/cluster-validation/{validationId}/details": {
      "get": {
        "operationId": "getClusterValidationDetail",
        "summary": "Get cluster validation run details",
        "description": "Returns the full detail for a specific cluster-validation run on your fleet: run state, the node names included, whether it was a Kubernetes-aware run, and timestamps.",
        "tags": [
          "Cluster Validation"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "validationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Cluster-validation run id (from the trigger or list response)."
          }
        ],
        "responses": {
          "200": {
            "description": "Cluster-validation run detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClusterValidationDetail"
                }
              }
            }
          },
          "400": {
            "description": "Fleet does not support cluster validation, or the validation id is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet or validation run not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/cluster-validation/{validationId}/report": {
      "get": {
        "operationId": "getClusterValidationReport",
        "summary": "Get cluster validation run report",
        "description": "Returns the per-node pass/fail report for a specific cluster-validation run on your fleet, including a summary for each result. When a result has no summary available (for example, a test that could not run), a generic message is returned in its place.",
        "tags": [
          "Cluster Validation"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "validationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Cluster-validation run id (from the trigger or list response)."
          }
        ],
        "responses": {
          "200": {
            "description": "Cluster-validation report",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClusterValidationReportResponse"
                }
              }
            }
          },
          "400": {
            "description": "Fleet does not support cluster validation, or the validation id is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet or validation run not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/cluster-validation/tests": {
      "get": {
        "operationId": "listClusterValidationTests",
        "summary": "List available cluster validation tests",
        "description": "Lists the cluster-validation tests available for your fleet, grouped by category, each with a short description. Which tests are returned depends on the fleet's type.",
        "tags": [
          "Cluster Validation"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Available cluster-validation tests grouped by category",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClusterValidationCatalogResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/storage/modify": {
      "post": {
        "operationId": "modifyFleetStorage",
        "summary": "Resize fleet storage",
        "description": "Increase or decrease the storage capacity for your fleet. Only the size can be changed - mount points and number of storage volumes stay the same.\n\n**When to use:**\n- Increase storage when running out of space\n- Decrease storage to reduce costs\n- Adjust capacity for different workload requirements\n\n**Important constraints:**\n- Only change size - can't add/remove storage volumes\n- Must match existing mount points exactly\n- Fleet remains available during resize",
        "tags": [
          "Fleet Operations"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier",
            "example": "900e8eac-2b1f-421f-a635-72556268b41f"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ModifyStorageRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Storage modification initiated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModifyStorageResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid storage modification request, or the storage service refused the change, for example because storage is not active. Retry later; contact support if it persists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "The fleet does not have storage provisioned yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fleets/{fleetId}/sshkeys": {
      "post": {
        "operationId": "addFleetSSHKey",
        "summary": "Apply an SSH key to a running fleet",
        "description": "Applies an SSH key already registered in the organization to a fleet that is already running, so its nodes accept the key without being rebuilt. Org-scoped: the caller's JWT org must own both the fleet and the key.\n\nKeys are only added. A key already on a node is left alone, and keys on a node that are not in the request are never removed \u2014 this endpoint cannot revoke access. Re-submitting the same key is safe and is the way to repair a fleet where an earlier attempt reached only some nodes.\n\nReturns 202 once the infrastructure service has accepted the work; the keys are written to nodes asynchronously. There is no status endpoint in this iteration \u2014 confirm by logging in. Only nodes that are already provisioned are visited; nodes added later pick the key up from the reservation's cloud-init.",
        "tags": [
          "SSH Keys"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddFleetSSHKeyRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Key propagation accepted. Nodes are updated asynchronously.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddFleetSSHKeyResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid fleet identifier or request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid JWT",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Caller does not have the Administrator role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet or SSH key not found (or not owned by the caller's org)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Fleet is not in a state that accepts key propagation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream infrastructure returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/sshkeys/{sshKeyId}": {
      "delete": {
        "operationId": "removeFleetSSHKey",
        "summary": "Revoke an SSH key from a running fleet",
        "description": "Removes every public key held by an SSH key record from a fleet's running nodes, so those nodes stop accepting them. Org-scoped: the caller's JWT org must own both the fleet and the key.\n\nThe fleet is named explicitly, and only that fleet is touched. Other fleets holding the same key keep it, and a node that never had the user is left alone rather than having the account created for it.\n\nThe passwordless sudo rule the infrastructure service granted the user on this fleet is removed along with the keys. Sudo from any other source \u2014 the fleet's cloud-init, or membership of the sudo group \u2014 is not touched.\n\nThe key stays registered in the organization and can be applied again later. To delete the record itself, use DELETE /v1/sshkeys/{sshKeyId}.\n\nReturns 202 once the infrastructure service has accepted the work; the nodes are updated asynchronously. There is no status endpoint in this iteration \u2014 confirm by attempting to log in. Re-submitting is safe.\n\nNodes added to the fleet after this call can still pick the key up from the reservation's cloud-init, which this endpoint does not rewrite.",
        "tags": [
          "SSH Keys"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "sshKeyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Identifier of an SSH key record in the caller's organization. Every public key held by that record is removed from the fleet."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Key revocation accepted. Nodes are updated asynchronously.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RemoveFleetSSHKeyResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid fleet or SSH key identifier",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid JWT",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Caller does not have the Administrator role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet or SSH key not found (or not owned by the caller's org)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Fleet is not in a state that accepts key changes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream infrastructure returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/storage/views": {
      "get": {
        "operationId": "listStorageViews",
        "summary": "List VAST storage views",
        "description": "Lists the physical VAST storage views (mount points and their quotas) provisioned for the fleet's reservation. Org-scoped: the caller's JWT org must own the fleet. Each returned view carries a `state` field; use it to confirm provisioning completion (poll until `state == \"active\"`). If the fleet exists but storage has not been materialized yet, returns 200 with `items: []` and `storagePending: true`.",
        "tags": [
          "Storage"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Storage views for the fleet's reservation. When the fleet exists but storage has not been materialized yet, `items` is empty and `storagePending` is true.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageViewListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Fleet's stored reservation identifier is malformed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid JWT",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found (or not owned by the caller's org)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream infrastructure service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "addStorageView",
        "summary": "Add a VAST storage view",
        "description": "Adds a new physical VAST storage view (mount point with size/quota) to the fleet's reservation, optionally triggering VAST provisioning. Org-scoped: the caller's JWT org must own the fleet. Returns 202 with the freshly-added view carrying `state: \"provisioning\"`; callers should poll `GET /v1/fleets/{fleetId}/storage/views/{view}` until `state == \"active\"` to confirm provisioning completion.",
        "tags": [
          "Storage"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddStorageViewRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Storage view add accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageView"
                }
              }
            }
          },
          "400": {
            "description": "Invalid fleet identifier or invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid JWT",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found (or not owned by the caller's org)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A storage view with this mount point already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream infrastructure service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/storage/views/{view}": {
      "get": {
        "operationId": "getStorageView",
        "summary": "Get a VAST storage view",
        "description": "Returns a single physical VAST storage view by mount point. Org-scoped: the caller's JWT org must own the fleet. The `state` field on the response is the source of truth for provisioning progress; poll this endpoint after a 202 from add/update until `state == \"active\"` (or `unhealthy` to fail fast).",
        "tags": [
          "Storage"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "view",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Storage view identifier (mount point, without a leading slash)."
          }
        ],
        "responses": {
          "200": {
            "description": "The storage view.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageView"
                }
              }
            }
          },
          "400": {
            "description": "Invalid fleet identifier or invalid view path segment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid JWT",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found (or not owned by the caller's org), or storage view not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream infrastructure service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "updateStorageView",
        "summary": "Update a VAST storage view",
        "description": "Updates the size/quota of a single physical VAST storage view by mount point. Org-scoped: the caller's JWT org must own the fleet. Returns 202 with the post-update view state.",
        "tags": [
          "Storage"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "view",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Storage view identifier (mount point, without a leading slash)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateStorageViewRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Storage view update accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageView"
                }
              }
            }
          },
          "400": {
            "description": "Invalid fleet identifier, invalid view path segment, or invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid JWT",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found (or not owned by the caller's org), or storage view not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream infrastructure service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteStorageView",
        "summary": "Delete a VAST storage view",
        "description": "Deletes a single physical VAST storage view by mount point. Org-scoped: the caller's JWT org must own the fleet.",
        "tags": [
          "Storage"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "view",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Storage view identifier (mount point, without a leading slash)."
          }
        ],
        "responses": {
          "204": {
            "description": "Storage view deleted."
          },
          "400": {
            "description": "Invalid fleet identifier or invalid view path segment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid JWT",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found (or not owned by the caller's org), or storage view not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream infrastructure service returned an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/history": {
      "get": {
        "operationId": "getFleetHistory",
        "summary": "Get fleet event history",
        "description": "Get the lifecycle history for a fleet, newest first: creation, status changes (including scaling and termination), storage changes, and node remediation requests.\n\n**When to use:**\n- Show fleet activity timeline in your UI\n- Audit what happened to a fleet\n- Debug issues by reviewing recent events\n\n**Pagination:** Some events are omitted from the history, so a page can contain fewer events than `limit`, or none, while `nextToken` is still returned. Keep requesting pages until `nextToken` is absent.",
        "tags": [
          "Fleets"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier",
            "example": "900e8eac-2b1f-421f-a635-72556268b41f"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 1000
            },
            "description": "Maximum number of events per page (default: 1000, max: 1000)",
            "example": 50
          },
          {
            "name": "nextToken",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Token from previous response to get next page of events"
          }
        ],
        "responses": {
          "200": {
            "description": "Success - returns paginated fleet history events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FleetHistoryResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fleets/{fleetId}/nodes": {
      "get": {
        "operationId": "listNodesByFleetId",
        "summary": "List nodes in a fleet",
        "description": "Get all GPU nodes in a fleet with their current status, IP addresses, and health information.\n\n**When to use:**\n- Display node list in your fleet dashboard\n- Check which nodes are ready for workloads\n- Monitor node health across the fleet\n- Get SSH connection details for nodes\n\n**Response includes:** Node status, private/public IPs, GPU info, and health status.",
        "tags": [
          "Nodes"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier",
            "example": "900e8eac-2b1f-421f-a635-72556268b41f"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 100
            },
            "description": "Nodes per page (default: 100)",
            "example": 100
          },
          {
            "name": "nextToken",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Token from previous response for next page"
          }
        ],
        "responses": {
          "200": {
            "description": "Success - returns paginated list of nodes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListNodesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid pagination parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fleets/{fleetId}/nodes/{nodeId}": {
      "get": {
        "operationId": "getNodeByFleetId",
        "summary": "Get node details",
        "description": "Get detailed information about a specific GPU node, including IP addresses, health status, and connection details.\n\n**When to use:**\n- Get SSH connection info for a specific node\n- Check detailed health status of a node\n- Troubleshoot issues with a particular node\n- Display node details in your UI",
        "tags": [
          "Nodes"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier",
            "example": "900e8eac-2b1f-421f-a635-72556268b41f"
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Node identifier (from list nodes response)",
            "example": "i-0abc123def456"
          }
        ],
        "responses": {
          "200": {
            "description": "Success - returns complete node information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Node"
                }
              }
            }
          },
          "404": {
            "description": "Node not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fleets/{fleetId}/nodes/{nodeId}/details": {
      "get": {
        "operationId": "getFleetNodeDetails",
        "summary": "Get consolidated node details",
        "description": "Returns consolidated single-node details for the node-details page: base physical fields (publicIp only), advisory powerActionReadiness, and optional managed-service data. Org-scoped: the caller's JWT org must own the fleet and the node must belong to that fleet.\n\nNet-new endpoint \u2014 does not replace GET /v1/fleets/{fleetId}/nodes/{nodeId}.",
        "tags": [
          "Nodes"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier"
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Node identifier (fleet node id)",
            "example": "g0546"
          }
        ],
        "responses": {
          "200": {
            "description": "Success - returns consolidated node details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodeDetails"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet or node not found, or node not in the caller's org/fleet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream infrastructure failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/fleets/{fleetId}/nodes/{nodeId}/power": {
      "get": {
        "operationId": "getNodePowerState",
        "summary": "Get node power state",
        "description": "Returns the node's power state and, when available, the most recent power operation. This read is eventually consistent. powerState is the last confirmed value, not a live hardware read on every call. It can stay at the previous value while a power operation is in progress, and a power change that did not go through this API can take up to 5 minutes to appear. The value is refreshed from the hardware when the confirmation is older than 5 minutes, and again when the operation finishes. While lastOperation is ACCEPTED or IN_PROGRESS, wait 10 to 15 seconds between calls. The response includes Retry-After while that operation is still running.",
        "tags": [
          "Nodes"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier",
            "example": "900e8eac-2b1f-421f-a635-72556268b41f"
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Node identifier (from list nodes response)",
            "example": "g311"
          }
        ],
        "responses": {
          "200": {
            "description": "The node's last confirmed power state.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before calling again while the power operation is still running.",
                "schema": {
                  "type": "integer",
                  "example": 15
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodePowerState"
                }
              }
            }
          },
          "400": {
            "description": "Fleet has an invalid reservation ID, or nodeId is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet or node not found, or the fleet has no reservation yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream infrastructure service returned an error, or the node's BMC is unreachable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createNodePowerOperation",
        "summary": "Queue a node power operation",
        "description": "Queues a power transition on a node via its BMC. Valid transitions depend on the node's current power state. Requires the Administrator role. Requests from Users are rejected with 403. Unknown reset types are rejected with 400.",
        "tags": [
          "Node Operations"
        ],
        "parameters": [
          {
            "name": "fleetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Fleet identifier",
            "example": "900e8eac-2b1f-421f-a635-72556268b41f"
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Node identifier (from list nodes response)",
            "example": "g311"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 255
            },
            "description": "Unique key for idempotent retries. Required for power operations."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NodePowerOperation"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay \u2014 the operation already completed. The response body contains the terminal outcome.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodePowerOperationQueued"
                }
              }
            }
          },
          "202": {
            "description": "Power operation accepted and queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodePowerOperationQueued"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body or unknown resetType",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated but the caller does not have the Administrator role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Fleet or node not found, or the fleet has no reservation yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Requested transition conflicts with the node's current power state, or a request with the same Idempotency-Key is currently in progress",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key already used with a different request body, method, path, or organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "423": {
            "description": "Another power operation is already in progress on this node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure before the upstream call",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Upstream infrastructure service returned an error, or the node's BMC is unreachable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Born-dead \u2014 the operation was recorded but the upstream BMC queue rejected it immediately. The response body contains the failure record. Clients may retry with a new Idempotency-Key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodePowerOperationQueued"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/sshkeys": {
      "post": {
        "operationId": "createSSHKey",
        "summary": "Add an SSH key",
        "description": "Register your SSH public key for secure access to fleet nodes. Once added, this key will be automatically installed on all new nodes in your fleets.\n\n**When to use:**\n- First time setup - add your SSH key before creating fleets\n- Team member needs access - add their public key\n- Rotate keys - add new key before removing old one\n\n**Supported formats:** OpenSSH, RFC4716, PKCS8, PKCS1 (automatically normalized to OpenSSH)\n\n**Idempotent:** Use `Idempotency-Key` header to safely retry if your request times out.",
        "tags": [
          "SSH Keys"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSSHKeyRequest"
              },
              "example": {
                "username": "john_doe",
                "publicKey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl user@example.com",
                "description": "Work laptop"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SSH key appended to an existing user record. Returned when the request's `username` already has an SSH-key record for the caller's organization; the new public key is appended to that record and the full updated SSH key is returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SSHKey"
                }
              }
            }
          },
          "201": {
            "description": "New SSH-key record created. Returned when the request's `username` had no SSH-key record yet for the caller's organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SSHKey"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid SSH key format or validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict - duplicate key name or fingerprint",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listSSHKeys",
        "summary": "List your SSH keys",
        "description": "Get all SSH keys registered for your organization. These keys are automatically installed on fleet nodes for secure access.\n\n**When to use:**\n- Show available SSH keys in your UI\n- Verify which keys are registered\n- Check key fingerprints before adding duplicates",
        "tags": [
          "SSH Keys"
        ],
        "responses": {
          "200": {
            "description": "Success - returns array of SSH keys",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SSHKey"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sshkeys/{sshKeyId}": {
      "delete": {
        "operationId": "deleteSSHKey",
        "summary": "Remove an SSH key",
        "description": "Remove an SSH key from your organization. The key will no longer be installed on new fleet nodes.\n\n**When to use:**\n- Revoke access when a team member leaves\n- Remove compromised keys\n- Clean up unused keys\n\n**Important:** Existing nodes keep the key until they're replaced. This operation is idempotent - safe to call multiple times.\n\n**Fleets:** If the user's keys were applied to running fleets, they are taken off those fleets' nodes first. If a fleet can't be reached, the user is kept and the response is 502 with `details.fleetIds`, but the fleets that were reached are already updated; retry to finish.\n\n**Slurm:** Slurm cluster users are separate from SSH keys. Deleting an SSH key does not change any Slurm cluster.",
        "tags": [
          "SSH Keys"
        ],
        "parameters": [
          {
            "name": "sshKeyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "SSH key identifier (from list SSH keys response)",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "SSH key deleted successfully"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "SSH key not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The user's keys are still on one or more fleets (listed in details.fleetIds), so it was not deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT token from Auth0. Include in the Authorization header as: `Bearer <token>`. Contact Voltage Park to get API credentials and access tokens."
      }
    },
    "schemas": {
      "FleetManagedBy": {
        "type": "string",
        "enum": [
          "MANAGED_KUBERNETES"
        ],
        "description": "A service whose controller owns a fleet's size. While a fleet has one, only that service can scale it."
      },
      "FleetComputeFootprint": {
        "type": "object",
        "properties": {
          "gpuNodes": {
            "$ref": "#/components/schemas/FleetNodeSpec"
          }
        },
        "required": [
          "gpuNodes"
        ]
      },
      "ExpandableCapacity": {
        "type": "object",
        "properties": {
          "gpuNodes": {
            "$ref": "#/components/schemas/ExpandableNodeSpec"
          }
        }
      },
      "InfrastructureNetwork": {
        "type": "string",
        "enum": [
          "infiniband",
          "ethernet"
        ],
        "description": "Network topology type",
        "example": "infiniband"
      },
      "FleetNodeSpec": {
        "type": "object",
        "properties": {
          "instanceType": {
            "type": "string",
            "description": "Server-derived compute instance type. `mixed` means the nodes have different GPU models; `unknown` means the hardware could not be determined.",
            "example": "h100-8x-bm"
          },
          "replicas": {
            "type": "integer",
            "description": "Number of replicas (deprecated: use nodes array instead)",
            "deprecated": true,
            "example": 2
          },
          "reserved_nodes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of reserved node identifiers (deprecated: use nodes array instead)",
            "deprecated": true,
            "example": [
              "g0386",
              "g0387"
            ]
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FleetNode"
            },
            "description": "List of actual node details with IPs",
            "example": [
              {
                "nodeName": "g0386",
                "publicIp": "10.9.41.182",
                "state": "ACTIVE"
              }
            ]
          }
        },
        "required": [
          "instanceType"
        ]
      },
      "ExpandableNodeSpec": {
        "type": "object",
        "properties": {
          "instanceType": {
            "type": "string",
            "description": "Server-derived compute instance type. `mixed` means the nodes have different GPU models; `unknown` means the hardware could not be determined.",
            "example": "h100-8x-bm"
          },
          "maxReplicas": {
            "type": "integer",
            "description": "Maximum number of replicas",
            "example": 20
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FleetNode"
            },
            "description": "READ-ONLY: List of actual node details with IPs. This field is populated automatically during scaling operations and should not be provided in creation requests.",
            "readOnly": true,
            "example": [
              {
                "nodeName": "g0386",
                "publicIp": "10.9.41.182",
                "state": "ACTIVE"
              }
            ]
          }
        },
        "required": [
          "instanceType",
          "maxReplicas"
        ]
      },
      "Infrastructure": {
        "type": "object",
        "properties": {
          "network": {
            "$ref": "#/components/schemas/InfrastructureNetwork"
          },
          "vast": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StorageConfig"
            },
            "description": "Storage configuration"
          }
        },
        "required": [
          "network"
        ]
      },
      "StorageConfig": {
        "type": "object",
        "properties": {
          "mountPoint": {
            "type": "string",
            "description": "Mount point for storage",
            "example": "/data"
          },
          "size": {
            "type": "integer",
            "format": "int64",
            "minimum": 1,
            "description": "Storage size in bytes",
            "example": 10737418240
          }
        },
        "required": [
          "mountPoint",
          "size"
        ]
      },
      "Bootstrap": {
        "type": "object",
        "description": "Bootstrap configuration for fleet nodes. Provide either sshUsers (recommended) or ssh-pub-keys for SSH access.",
        "properties": {
          "cloudInit": {
            "type": "string",
            "description": "Node setup applied by cloud-init on every node, including nodes added by scaling. Accepts a script that starts with `#!`, a `#cloud-config` document, or plain shell commands, which run with bash. `#include`, `#cloud-boothook`, Jinja templates, `#part-handler`, MIME multi-part, and compressed content are rejected. A `#cloud-config` document must be a single YAML mapping that cloud-init can load; if it sets `users`, that must be a list of names or user mappings. It must not configure disks or filesystems, change cloud-init's module lists, or mount over or inside system directories or the fleet's storage mount points; mount paths must not contain `..`.",
            "example": "sudo ls -a"
          },
          "machineImage": {
            "type": "string",
            "description": "Machine image to use. On a Managed Kubernetes v2 fleet, an image whose name marks it as built for a different CPU architecture (amd64 or arm64) than the selected nodes is rejected.",
            "example": "Ubuntu 24.04"
          },
          "sshUsers": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of SSH usernames from your organization's SSH key management. Each user's public keys will be added and a corresponding Linux user will be created on each node.",
            "example": [
              "john_doe",
              "jane_smith"
            ]
          },
          "ssh-pub-keys": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "deprecated": true,
            "description": "DEPRECATED: Use sshUsers instead. Raw keys for backward compatibility only.",
            "example": [
              "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC...",
              "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG..."
            ]
          },
          "sudoAccess": {
            "type": "string",
            "enum": [
              "enabled",
              "disabled"
            ],
            "description": "Controls sudo access for the SSH users the API creates on every node in the fleet (both sshUsers and the deprecated ssh-pub-keys path). When enabled, each API-managed user is granted passwordless sudo; when disabled, users are created without any API-managed sudo rule. Applies to standalone bare-metal fleets and is fixed at creation time. Defaults to enabled.",
            "example": "enabled"
          }
        },
        "required": [
          "machineImage"
        ]
      },
      "FleetApps": {
        "type": "object",
        "description": "Fleet applications configuration. Legacy managed Kubernetes (`mk8s`) and mks2 are mutually exclusive: at most one of them may be 'enabled' on the same fleet.",
        "properties": {
          "mk8s": {
            "type": "string",
            "enum": [
              "enabled",
              "disabled"
            ],
            "description": "Enable or disable legacy managed Kubernetes for this fleet. Mutually exclusive with mks2.",
            "example": "disabled"
          },
          "mks2": {
            "type": "string",
            "enum": [
              "enabled",
              "disabled"
            ],
            "description": "Enable or disable managed Kubernetes for this fleet. Mutually exclusive with mk8s.",
            "example": "disabled"
          },
          "slurm": {
            "type": "string",
            "enum": [
              "enabled",
              "disabled"
            ],
            "description": "Enable or disable Slurm for this fleet",
            "example": "disabled"
          },
          "mk8sCluster": {
            "allOf": [
              {
                "$ref": "#/components/schemas/FleetAppsMksCluster"
              }
            ],
            "description": "Legacy managed Kubernetes cluster information (only present when mk8s is enabled)"
          },
          "mks2Cluster": {
            "allOf": [
              {
                "$ref": "#/components/schemas/FleetAppsMks2Cluster"
              }
            ],
            "description": "Managed Kubernetes cluster information (only present when mks2 is enabled)"
          },
          "slurmParameters": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SlurmParameters"
              }
            ],
            "description": "Slurm configuration (only present when slurm is enabled)"
          }
        },
        "additionalProperties": false
      },
      "OsConfig": {
        "type": "object",
        "description": "Declarative, intent-based OS tuning applied to the operating system of every node in the fleet. Each capability is requested by name; the API owns the known-good translation to node-level configuration and re-applies it on scale-up so new nodes inherit the same tuning. All capabilities are optional; omit the whole object to keep node OS defaults.",
        "properties": {
          "cpuProfiling": {
            "type": "string",
            "enum": [
              "enabled",
              "disabled"
            ],
            "description": "Enable non-root, system-wide CPU profiling on every node (e.g. `perf top`, `perf stat -a`). When enabled, the API applies the required node kernel settings automatically. Defaults to disabled.",
            "example": "disabled"
          },
          "gpuProfiling": {
            "type": "string",
            "enum": [
              "enabled",
              "disabled"
            ],
            "description": "Enable non-root GPU performance-counter profiling on every node (e.g. NVIDIA Nsight Compute `ncu`). When enabled, the API applies the required NVIDIA driver settings automatically. The profiler itself must already be present in the node image; the API only grants access to the counters. Bare-metal fleets only: on managed Kubernetes the NVIDIA driver is managed by the GPU operator rather than by node startup configuration, so enabling it there is rejected. Defaults to disabled.",
            "example": "disabled"
          }
        },
        "additionalProperties": false
      },
      "SlurmParameters": {
        "type": "object",
        "description": "Configuration parameters for SLURM addon",
        "properties": {
          "sshKeys": {
            "type": "array",
            "description": "SSH user configurations with multiple keys per user",
            "minItems": 1,
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Username for SSH access",
                  "pattern": "^[a-zA-Z_][a-zA-Z0-9._-]*$",
                  "minLength": 1,
                  "maxLength": 32,
                  "example": "user"
                },
                "keys": {
                  "type": "array",
                  "description": "List of SSH public keys for this user",
                  "minItems": 1,
                  "maxItems": 10,
                  "items": {
                    "type": "string",
                    "description": "SSH public key content",
                    "pattern": "^(ssh-rsa|ssh-ed25519|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521) [A-Za-z0-9+/=]+( .*)?$",
                    "example": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl user@voltagepark.com"
                  }
                }
              },
              "required": [
                "name",
                "keys"
              ]
            }
          },
          "externalStorage": {
            "$ref": "#/components/schemas/ExternalStorageConfig",
            "description": "External storage configuration for SLURM"
          },
          "controlPlaneNodes": {
            "type": "array",
            "description": "Node IDs of the Slurm control-plane nodes. These nodes are labeled with slurm.voltagepark.io/node-role=control-plane before activating the Helm chart. Install-only \u2014 optional at fleet creation; ignored if empty.",
            "items": {
              "type": "string",
              "description": "K8s node name / hostname",
              "minLength": 1
            }
          },
          "controlPlanePlacement": {
            "type": "string",
            "enum": [
              "shared",
              "dedicated"
            ],
            "description": "Whether the control-plane nodes also run Slurm jobs. shared: they run a worker too, so one GPU node is a complete Slurm cluster; give 1 or 2 controlPlaneNodes (when omitted, the first GPU node not listed in loginNodes, or the first GPU node if all are). dedicated: they run only Slurm's controllers, and at least one GPU node must remain a worker. When omitted: dedicated if controlPlaneNodes is set, otherwise shared."
          },
          "slurmVersion": {
            "type": "string",
            "enum": [
              "24",
              "26"
            ],
            "description": "Slurm major version to install: 24 or 26. When omitted, the default applies: Slurm 26 wherever it is available, otherwise Slurm 24. Slurm 24 is not available on arm64 (GB300) nodes, so asking for it there is rejected. It applies at install: a fleet on Slurm 24 can later be upgraded in place to Slurm 26 from its Slurm tab, which updates this value."
          },
          "loginNodes": {
            "type": "array",
            "description": "Node IDs of the Slurm login nodes. These nodes are labeled with slurm.voltagepark.io/login-node=true. Kept separate from controlPlaneNodes so a rogue login pod cannot disrupt slurmctld/slurmdbd.",
            "items": {
              "type": "string",
              "description": "K8s node name / hostname",
              "minLength": 1
            }
          }
        },
        "required": [
          "sshKeys",
          "externalStorage"
        ]
      },
      "FleetAppsMksCluster": {
        "type": "object",
        "description": "Legacy managed Kubernetes cluster information for this fleet",
        "properties": {
          "clusterId": {
            "type": "string",
            "description": "Legacy managed Kubernetes cluster ID",
            "example": "cluster-123-abc"
          },
          "clusterName": {
            "type": "string",
            "description": "Legacy managed Kubernetes cluster name",
            "example": "my-fleet-k8s-cluster"
          },
          "kubernetesVersion": {
            "type": "string",
            "description": "Kubernetes version running on the cluster",
            "example": "1.32"
          },
          "installationStatus": {
            "type": "string",
            "description": "Legacy managed Kubernetes installation status on the fleet",
            "enum": [
              "CREATING",
              "PROVISIONING",
              "ACTIVE",
              "ERROR"
            ],
            "example": "ACTIVE"
          },
          "clusterStatus": {
            "type": "string",
            "description": "Current legacy managed Kubernetes cluster status from Kubernetes API",
            "enum": [
              "PENDING",
              "PROVISIONING",
              "READY",
              "UPDATING",
              "DEGRADED",
              "FAILED",
              "DELETING",
              "TERMINATED",
              "SHUTTING_DOWN",
              "STARTING",
              "STOPPED"
            ],
            "example": "READY"
          },
          "kubeconfig": {
            "type": "string",
            "description": "The kubeconfig for accessing the cluster (if available)",
            "example": "apiVersion: v1\\nkind: Config\\n..."
          },
          "serviceLinks": {
            "$ref": "#/components/schemas/KubernetesServiceLinks"
          },
          "controlPlaneNodeCount": {
            "type": "integer",
            "description": "Number of control plane nodes",
            "example": 3
          },
          "readyControlPlaneNodeCount": {
            "type": "integer",
            "nullable": true,
            "description": "Number of ready control plane nodes",
            "example": 3
          },
          "workerNodeCount": {
            "type": "integer",
            "nullable": true,
            "description": "Number of worker nodes",
            "example": 8
          },
          "readyWorkerNodeCount": {
            "type": "integer",
            "nullable": true,
            "description": "Number of ready worker nodes",
            "example": 8
          },
          "addons": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of installed addons",
            "example": [
              "prometheus"
            ]
          },
          "createdAt": {
            "type": "string",
            "description": "Timestamp when the cluster was created",
            "example": "2025-01-15T10:30:00Z"
          }
        },
        "required": [
          "clusterId",
          "clusterName",
          "installationStatus"
        ],
        "additionalProperties": false
      },
      "KubernetesServiceLinks": {
        "type": "object",
        "description": "Links to Kubernetes cluster services",
        "properties": {
          "grafana": {
            "type": "string",
            "format": "uri",
            "description": "URL to the Grafana dashboard for cluster monitoring",
            "example": "https://grafana.voltagepark.com/d/abc123/cluster-overview"
          }
        },
        "additionalProperties": false
      },
      "FleetAppsMks2Cluster": {
        "type": "object",
        "description": "Managed Kubernetes cluster information for this fleet. Sensitive fields (kubeconfig) are intentionally not surfaced here; they are fetched via a separate endpoint.\n\nAtomic populate-or-omit: when this object is present in a fleet response, every field is populated from a successful live cluster lookup. If managed Kubernetes is unreachable, this object is omitted from the parent applications object entirely - the response then has no mks2Cluster key at all. Clients should treat absent and present-but-incomplete as the same state (cluster details unavailable).",
        "properties": {
          "clusterId": {
            "type": "string",
            "description": "Managed Kubernetes cluster ID (stable across enrichment results)",
            "example": "11111111-2222-3333-4444-555555555555"
          },
          "clusterName": {
            "type": "string",
            "description": "Managed Kubernetes cluster name as reported by managed Kubernetes",
            "example": "my-fleet-k8s-cluster"
          },
          "kubernetesVersion": {
            "type": "string",
            "description": "Kubernetes version running on the cluster (e.g. v1.35.0)",
            "example": "v1.35.0"
          },
          "clusterStatus": {
            "type": "string",
            "description": "Live cluster status reported by managed Kubernetes (lowercase).",
            "enum": [
              "creating",
              "ready",
              "failed",
              "degraded",
              "updating",
              "deleting"
            ],
            "example": "ready"
          },
          "controlPlaneReplicas": {
            "type": "integer",
            "description": "Desired number of control plane replicas",
            "example": 2
          },
          "controlPlaneSize": {
            "type": "string",
            "enum": [
              "small",
              "medium",
              "large",
              "xlarge",
              "xxlarge"
            ],
            "description": "Control plane resource tier, which determines the CPU and memory allocated to the Kubernetes API server. Omitted while the cluster's control plane is still being provisioned.",
            "example": "medium"
          },
          "datastoreType": {
            "type": "string",
            "enum": [
              "shared",
              "dedicated"
            ],
            "description": "Whether the cluster runs on shared multi-tenant etcd or its own dedicated etcd cluster. Omitted when the cluster's etcd configuration is temporarily unavailable.",
            "example": "dedicated"
          },
          "nvidiaDriverVersion": {
            "type": "string",
            "description": "NVIDIA driver version installed via the GPU operator",
            "example": "580.126.20"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the managed Kubernetes cluster was created",
            "example": "2026-01-15T10:30:00Z"
          },
          "nodeCounts": {
            "$ref": "#/components/schemas/FleetAppsMks2NodeCounts"
          }
        },
        "required": [
          "clusterId",
          "clusterName",
          "kubernetesVersion",
          "clusterStatus",
          "controlPlaneReplicas",
          "nvidiaDriverVersion",
          "createdAt",
          "nodeCounts"
        ],
        "additionalProperties": false
      },
      "FleetAppsMks2NodeCounts": {
        "type": "object",
        "description": "Aggregate count summary of worker node status in the managed Kubernetes cluster. Mirrors the Kubernetes API. All counters are required to keep the parent FleetAppsMks2Cluster atomic-or-absent.",
        "properties": {
          "total": {
            "type": "integer",
            "description": "Total number of registered nodes",
            "example": 4
          },
          "ready": {
            "type": "integer",
            "description": "Nodes that are Ready in the Kubernetes sense",
            "example": 3
          },
          "notReady": {
            "type": "integer",
            "description": "Nodes that are registered but not Ready",
            "example": 1
          },
          "pending": {
            "type": "integer",
            "description": "Nodes registered but not yet joined to Kubernetes",
            "example": 0
          }
        },
        "required": [
          "total",
          "ready",
          "notReady",
          "pending"
        ],
        "additionalProperties": false
      },
      "KubeconfigV2Response": {
        "type": "object",
        "description": "Time-limited kubeconfig credential for a managed Kubernetes cluster. Returned by the customer kubeconfig endpoint as a short-lived, customer-scoped credential; refetch before `expiresAt`.",
        "properties": {
          "kubeconfig": {
            "type": "string",
            "description": "Complete kubeconfig YAML, ready to be written to disk and consumed by kubectl. Server URL points at the external cluster API endpoint."
          },
          "role": {
            "type": "string",
            "description": "Role this kubeconfig was generated for. Customer-scoped kubeconfigs return `customer`.",
            "example": "customer"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Absolute time at which the kubeconfig stops working. Clients should refetch before this expires.",
            "example": "2026-12-31T23:59:59Z"
          },
          "ttlSeconds": {
            "type": "integer",
            "description": "Time-to-live in seconds from the moment the kubeconfig was generated. Convenience hint - prefer expiresAt for absolute scheduling.",
            "example": 3600
          }
        },
        "required": [
          "kubeconfig",
          "role",
          "expiresAt",
          "ttlSeconds"
        ],
        "additionalProperties": false
      },
      "Mks2HealthStatus": {
        "type": "string",
        "description": "Health state for any managed Kubernetes component, node, or the cluster overall. `healthy` = all observed signals are nominal; `degraded` = partial functionality, some signals failing; `unhealthy` = no usable functionality from this component; `stopped` = intentionally scaled to zero (e.g. control plane replicas == 0); `unknown` = no signal available yet (probe pending, monitor not wired, etc.).",
        "enum": [
          "healthy",
          "degraded",
          "unhealthy",
          "stopped",
          "unknown"
        ],
        "example": "healthy"
      },
      "Mks2ComponentHealth": {
        "type": "object",
        "description": "Health for a single named component (e.g. Cilium, konnectivity, an addon). Every field is optional. `reason` is human-readable diagnostic text - do not match programmatically. `lastHealthyAt` is the last time the component reported healthy; `lastUpdated` is when the most recent observation was made (regardless of whether it was healthy).",
        "properties": {
          "status": {
            "$ref": "#/components/schemas/Mks2HealthStatus"
          },
          "reason": {
            "type": "string",
            "description": "Human-readable status detail; not stable for programmatic matching.",
            "example": "kube-apiserver Pod in CrashLoopBackOff"
          },
          "lastUpdated": {
            "type": "string",
            "format": "date-time",
            "description": "When this component's status was last observed.",
            "example": "2026-05-11T10:30:00Z"
          },
          "lastHealthyAt": {
            "type": "string",
            "format": "date-time",
            "description": "Last timestamp at which this component reported healthy. Absent if upstream did not include it.",
            "example": "2026-05-11T10:00:00Z"
          }
        }
      },
      "Mks2ControlPlaneHealth": {
        "type": "object",
        "description": "Health of the cluster's control plane (managed Kubernetes tenant-cluster API server + controller-manager + scheduler). Replicas and readyReplicas reflect the live observed counts when published, falling back to the desired count from the spec when no observed status is available yet.",
        "properties": {
          "status": {
            "$ref": "#/components/schemas/Mks2HealthStatus"
          },
          "replicas": {
            "type": "integer",
            "description": "Total control-plane replicas (observed if available, else desired).",
            "example": 2
          },
          "readyReplicas": {
            "type": "integer",
            "description": "Number of control-plane replicas currently Ready.",
            "example": 2
          },
          "reason": {
            "type": "string",
            "description": "Human-readable detail; populated when degraded/unhealthy.",
            "example": "1/2 replicas not ready"
          },
          "lastUpdated": {
            "type": "string",
            "format": "date-time",
            "description": "When the control plane's status was last observed.",
            "example": "2026-05-11T10:30:00Z"
          }
        }
      },
      "Mks2NodeHealth": {
        "type": "object",
        "description": "Per-worker-node health snapshot. Identifier is the managed Kubernetes registry id; the upstream service intentionally does not expose Kubernetes node names or full conditions maps here - per-node detail belongs in the dedicated nodes endpoint.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Managed Kubernetes node identifier (registry ID).",
            "example": "g0546"
          },
          "status": {
            "$ref": "#/components/schemas/Mks2HealthStatus"
          },
          "reason": {
            "type": "string",
            "description": "Human-readable detail; not stable for programmatic matching.",
            "example": "Health monitoring not yet available"
          },
          "lastUpdated": {
            "type": "string",
            "format": "date-time",
            "description": "When this node's health was last observed.",
            "example": "2026-05-11T10:30:00Z"
          },
          "lastHealthyAt": {
            "type": "string",
            "format": "date-time",
            "description": "Last time this node reported healthy.",
            "example": "2026-05-11T10:00:00Z"
          }
        }
      },
      "Mks2NetworkHealth": {
        "type": "object",
        "description": "Health of the cluster's networking layer. cilium covers the CNI; konnectivity covers API-server-to-worker connectivity. Both are absent until their respective monitors are wired upstream - treat absence as no signal, not as healthy.",
        "properties": {
          "cilium": {
            "$ref": "#/components/schemas/Mks2ComponentHealth"
          },
          "konnectivity": {
            "$ref": "#/components/schemas/Mks2ComponentHealth"
          }
        }
      },
      "Mks2AddonsHealth": {
        "type": "object",
        "description": "Per-addon health monitors. Each sub-field is absent until its monitor is wired upstream; treat absence as no signal, not as healthy.",
        "properties": {
          "slurm": {
            "$ref": "#/components/schemas/Mks2ComponentHealth"
          },
          "prometheus": {
            "$ref": "#/components/schemas/Mks2ComponentHealth"
          },
          "efs": {
            "$ref": "#/components/schemas/Mks2ComponentHealth"
          }
        }
      },
      "Mks2ClusterHealth": {
        "type": "object",
        "description": "Comprehensive managed Kubernetes cluster health snapshot. Mirrors the Kubernetes API; `status` is the only required field (upstream always emits an overall health), every other field is optional and may be absent depending on which monitors have run. Consumers should treat missing fields as 'no signal' rather than 'healthy'.",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/Mks2HealthStatus"
          },
          "controlPlane": {
            "$ref": "#/components/schemas/Mks2ControlPlaneHealth"
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Mks2NodeHealth"
            },
            "description": "Per-worker-node health entries. Always worker-side; control-plane health lives in the controlPlane field above."
          },
          "network": {
            "$ref": "#/components/schemas/Mks2NetworkHealth"
          },
          "addons": {
            "$ref": "#/components/schemas/Mks2AddonsHealth"
          },
          "lastUpdated": {
            "type": "string",
            "format": "date-time",
            "description": "When the upstream health-collector last produced this snapshot. Absent if the collector has not run yet.",
            "example": "2026-05-11T10:30:00Z"
          },
          "lastHealthyAt": {
            "type": "string",
            "format": "date-time",
            "description": "Last time the cluster overall reported healthy.",
            "example": "2026-05-11T10:00:00Z"
          }
        }
      },
      "Mks2WorkerNodeRegistrationStatus": {
        "type": "string",
        "description": "Managed Kubernetes node registration status. `registered` means the node is in the managed Kubernetes worker registry but has not yet completed bootstrap; `joined` means the node has bootstrapped and joined the Kubernetes cluster. Mirrors the Kubernetes API.",
        "enum": [
          "registered",
          "joined"
        ],
        "example": "joined"
      },
      "Mks2WorkerNodeKubernetesStatus": {
        "type": "string",
        "description": "Kubernetes node status (only set when `registrationStatus = joined`). Mirrors the Kubernetes API.",
        "enum": [
          "Ready",
          "NotReady",
          "Unknown"
        ],
        "example": "Ready"
      },
      "Mks2NodeCondition": {
        "type": "object",
        "description": "A single condition on a managed Kubernetes worker node. Reported from the node's Kubernetes status; includes standard Kubernetes node conditions (Ready, MemoryPressure, DiskPressure, PIDPressure, NetworkUnavailable) and additional GPU/health conditions (e.g. GPUValidated).",
        "properties": {
          "type": {
            "type": "string",
            "description": "Condition type (e.g. Ready, MemoryPressure, DiskPressure, PIDPressure, NetworkUnavailable, GPUValidated).",
            "example": "MemoryPressure"
          },
          "status": {
            "type": "string",
            "description": "Condition status. One of True, False, Unknown.",
            "example": "False"
          },
          "reason": {
            "type": "string",
            "description": "Machine-readable reason for the condition's last transition."
          },
          "message": {
            "type": "string",
            "description": "Human-readable message describing the condition."
          },
          "lastTransitionTime": {
            "type": "string",
            "format": "date-time",
            "description": "When the condition last transitioned."
          }
        }
      },
      "Mks2GpuInfo": {
        "type": "object",
        "description": "GPU information for a managed Kubernetes worker node.",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of GPUs on the node."
          },
          "model": {
            "type": "string",
            "description": "GPU model name.",
            "example": "NVIDIA-H100-80GB-HBM3"
          },
          "driverVersion": {
            "type": "string",
            "description": "NVIDIA driver version."
          },
          "cudaRuntimeVersion": {
            "type": "string",
            "description": "CUDA runtime version."
          },
          "memory": {
            "type": "string",
            "description": "Total GPU memory per device in MiB."
          },
          "validated": {
            "type": "boolean",
            "description": "Whether GPU validation has passed for this node."
          }
        }
      },
      "Mks2WorkerNodeDetail": {
        "type": "object",
        "description": "Full managed Kubernetes worker-node detail: a superset of the list summary (Mks2WorkerNode) that adds per-node conditions, GPU info, labels/annotations, registration timestamps, and a live drain observation. Unlike the list (which only includes joined nodes), the per-node detail endpoint also resolves nodes that are registered but not yet joined. `gpuValidated` is a convenience mirror of `gpu.validated`.",
        "required": [
          "id",
          "registrationStatus"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Managed Kubernetes worker-node identifier (registry id). Stable for the lifetime of the registry entry.",
            "example": "g0546"
          },
          "name": {
            "type": "string",
            "description": "Kubernetes node name. Absent until the node has joined the cluster."
          },
          "registrationStatus": {
            "$ref": "#/components/schemas/Mks2WorkerNodeRegistrationStatus"
          },
          "kubernetesStatus": {
            "$ref": "#/components/schemas/Mks2WorkerNodeKubernetesStatus"
          },
          "schedulable": {
            "type": "boolean",
            "description": "Whether pods can be scheduled on this node (i.e. uncordoned). Absent when the node has not joined yet."
          },
          "drained": {
            "type": "boolean",
            "readOnly": true,
            "description": "Live Kubernetes control-plane observation of whether workloads have drained from this node. True when every Pod currently bound to the node is terminal, a mirror Pod, or owned by a live DaemonSet. False when any other Pod remains. Omitted before the node joins or when the tenant cluster cannot be fully observed. This field is independent from `schedulable`; callers preparing maintenance must also verify the node is cordoned. The observation is point-in-time and does not prove that no out-of-band process is running on the host."
          },
          "gpuValidated": {
            "type": "boolean",
            "description": "Whether managed Kubernetes has run GPU validation against this node and it passed. Convenience mirror of gpu.validated; absent when no GPU info is available."
          },
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Mks2NodeCondition"
            },
            "description": "Node conditions passed through from the tenant Kubernetes node, including custom node conditions. Absent until the node has joined."
          },
          "gpu": {
            "$ref": "#/components/schemas/Mks2GpuInfo"
          },
          "registeredAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the node was added to the managed Kubernetes worker registry."
          },
          "joinedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the node joined the Kubernetes cluster. Null/absent for registered-but-not-yet-joined nodes."
          },
          "labels": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Kubernetes node labels. Absent until the node has joined."
          },
          "annotations": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Kubernetes node annotations. Absent until the node has joined."
          },
          "publicIp": {
            "type": "string",
            "description": "Public IPv4 address of the node, used for source-IP-based request routing. Absent when the node was registered without a public IP."
          },
          "taints": {
            "type": "array",
            "description": "Live Kubernetes node taints. Absent until the node has joined.",
            "items": {
              "$ref": "#/components/schemas/Mks2NodeTaint"
            }
          },
          "maintenance": {
            "$ref": "#/components/schemas/Mks2NodeMaintenance",
            "description": "Maintenance state derived from the node's live taints and conditions. Absent until the node has joined the cluster."
          }
        }
      },
      "Mks2CordonNodeResponse": {
        "type": "object",
        "description": "Result of a cordon or uncordon operation. `schedulable` reflects the node's scheduling state after the operation (false after cordon, true after uncordon).",
        "required": [
          "nodeId",
          "schedulable"
        ],
        "properties": {
          "nodeId": {
            "type": "string",
            "description": "Managed Kubernetes worker-node identifier (registry id) the operation targeted.",
            "example": "g0546"
          },
          "schedulable": {
            "type": "boolean",
            "description": "Whether pods can be scheduled on the node after the operation. false after cordon, true after uncordon."
          },
          "message": {
            "type": "string",
            "description": "Human-readable status message describing the result, when available."
          }
        }
      },
      "Mks2DrainNodeRequest": {
        "type": "object",
        "description": "Optional tuning for a node drain. Every field is optional; omit the body (or any field) to use the defaults below. These defaults are owned and applied by the API, so an omitted, empty ({}), or partial body all behave identically.",
        "properties": {
          "gracePeriodSeconds": {
            "type": "integer",
            "format": "int32",
            "default": 30,
            "description": "Grace period (seconds) granted to evicted pods before they are forcibly terminated. Maps to the eviction grace period.",
            "example": 30
          },
          "deleteLocalData": {
            "type": "boolean",
            "default": false,
            "description": "Whether to evict pods backed by emptyDir / local storage (their data is lost). Not currently honored; accepted for forward compatibility and has no effect yet."
          },
          "ignoreDaemonSets": {
            "type": "boolean",
            "default": true,
            "description": "Whether to proceed with the drain even though DaemonSet-managed pods cannot be evicted (they are skipped)."
          }
        }
      },
      "Mks2DrainNodeResponse": {
        "type": "object",
        "description": "Result of a node drain. `evicted` and `failed` are included when reported.",
        "required": [
          "nodeId"
        ],
        "properties": {
          "nodeId": {
            "type": "string",
            "description": "Managed Kubernetes worker-node identifier (registry id) the drain targeted.",
            "example": "g0546"
          },
          "evicted": {
            "type": "integer",
            "format": "int32",
            "description": "Number of pods evicted from the node, when reported."
          },
          "failed": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Identifiers of pods that could not be evicted, when reported."
          }
        }
      },
      "CustomerTriggerClusterValidationRequest": {
        "type": "object",
        "description": "Request to start a cluster-validation run against your fleet's nodes. Runs are always multi-host; that is not configurable.",
        "properties": {
          "nodeNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional subset of fleet node names to validate. Each name must belong to your fleet. Omit (or send an empty list) to validate all nodes in the fleet.",
            "example": [
              "g0546",
              "g0547"
            ]
          },
          "kubernetes": {
            "type": "boolean",
            "default": false,
            "description": "When true, run Kubernetes-aware validation tests. Requires a Kubernetes-enabled fleet; the required cluster credential is obtained automatically and is never supplied by the caller."
          },
          "tests": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional list of test names to run (from the cluster-validation test catalog). Omit to run the default set of tests.",
            "example": [
              "nccl",
              "gpu-burn"
            ]
          }
        }
      },
      "ClusterValidationResponse": {
        "type": "object",
        "description": "Status of a cluster-validation run. The API surfaces the documented fields; additional fields reported by the upstream validator may be included for forward compatibility and should not be relied on.",
        "properties": {
          "validationId": {
            "type": "integer",
            "description": "Cluster-validation run id. Use it to poll status, abort, or download logs.",
            "example": 4213
          },
          "status": {
            "type": "string",
            "description": "Current run status (e.g. RUNNING, COMPLETED, FAILED, ABORTED).",
            "example": "RUNNING"
          }
        },
        "additionalProperties": true
      },
      "ClusterValidationDetail": {
        "type": "object",
        "description": "Typed view of a single cluster-validation run. The upstream validator's internal wire format is not exposed; callers code against the fields defined here.",
        "properties": {
          "validationId": {
            "type": "integer",
            "description": "Cluster-validation run id. Use it to poll status, abort, or download logs.",
            "example": 4213
          },
          "state": {
            "type": "string",
            "description": "Current run state.",
            "enum": [
              "PENDING",
              "PREP",
              "RUNNING",
              "CLEANUP",
              "ABORTING",
              "ABORTED",
              "SKIPPED",
              "COMPLETED",
              "UNHEALTHY"
            ],
            "example": "RUNNING"
          },
          "multiHost": {
            "type": "boolean",
            "description": "Whether the run executes a single test across all selected nodes (multi-host) rather than one test per node."
          },
          "kubernetes": {
            "type": "boolean",
            "description": "Whether the run uses Kubernetes-aware validation tests. Maps from the infrastructure service's k8s flag."
          },
          "nodeNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fleet node names included in this run.",
            "example": [
              "g0546",
              "g0547"
            ]
          },
          "requestId": {
            "type": "string",
            "nullable": true,
            "description": "Unique identifier for the underlying test request, when present."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the run was created."
          },
          "startTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the run became active."
          },
          "endTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the run ended, when applicable."
          }
        },
        "required": [
          "validationId",
          "state"
        ]
      },
      "ClusterValidationListResponse": {
        "type": "object",
        "description": "A bounded, newest-first list of recent cluster-validation runs for a fleet (capped at 10).",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClusterValidationDetail"
            },
            "description": "Recent runs, newest first. Empty array (not null) when the fleet has no runs."
          }
        },
        "required": [
          "items"
        ]
      },
      "ClusterValidationReportResponse": {
        "type": "object",
        "description": "Cluster-validation report passed through from the infrastructure service, including per-node pass/fail status and references for downloading individual result logs. Fields are passed through unchanged.",
        "additionalProperties": true
      },
      "ClusterValidationCatalogResponse": {
        "type": "object",
        "description": "Catalog of available cluster-validation tests grouped by category. Shaped as {\"categories\": {\"<category>\": {\"description\": \"...\", \"tests\": [{\"name\": \"...\", \"description\": \"...\"}]}}}.",
        "additionalProperties": true
      },
      "ExternalStorageConfig": {
        "type": "object",
        "description": "External storage configuration",
        "properties": {
          "mountPath": {
            "type": "string",
            "description": "Mount path for the external storage",
            "example": "/data"
          },
          "size": {
            "type": "string",
            "description": "Storage size",
            "example": "128GB",
            "pattern": "^[0-9]+[KMGT][Bi]?$"
          }
        },
        "required": [
          "mountPath",
          "size"
        ]
      },
      "Fleet": {
        "type": "object",
        "description": "A fleet represents a cluster of GPU nodes provisioned for your workloads",
        "properties": {
          "fleetId": {
            "type": "string",
            "description": "Unique identifier for the fleet",
            "example": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
          },
          "name": {
            "type": "string",
            "description": "Human-readable name for the fleet",
            "example": "text-to-video-demo"
          },
          "status": {
            "$ref": "#/components/schemas/FleetStatus"
          },
          "requestedAt": {
            "type": "integer",
            "description": "Timestamp when the fleet was requested (milliseconds since epoch UTC)",
            "example": 1755817319000
          },
          "provisionedAt": {
            "type": "integer",
            "description": "Timestamp when the fleet was provisioned (milliseconds since epoch UTC)",
            "example": 1755831319000
          },
          "createdAt": {
            "type": "integer",
            "description": "Timestamp when the fleet was created (milliseconds since epoch UTC)",
            "example": 1755817319000
          },
          "updatedAt": {
            "type": "integer",
            "description": "Timestamp when the fleet was last updated (milliseconds since epoch UTC)",
            "example": 1755831319000
          },
          "computeType": {
            "type": "string",
            "description": "Type of compute resources",
            "example": "BARE_METAL"
          },
          "minimumFootprint": {
            "$ref": "#/components/schemas/FleetComputeFootprint"
          },
          "expandableCapacity": {
            "$ref": "#/components/schemas/ExpandableCapacity"
          },
          "infrastructure": {
            "$ref": "#/components/schemas/Infrastructure"
          },
          "bootstrap": {
            "$ref": "#/components/schemas/Bootstrap"
          },
          "fleetApps": {
            "$ref": "#/components/schemas/FleetApps"
          },
          "osConfig": {
            "$ref": "#/components/schemas/OsConfig"
          },
          "orderId": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Linked order ID. Null if this fleet is not associated with an order.",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "managedBy": {
            "allOf": [
              {
                "$ref": "#/components/schemas/FleetManagedBy"
              }
            ],
            "readOnly": true,
            "description": "The service that manages this fleet's size, if any. While set, scale requests from anyone else are refused with code `FLEET_MANAGED_EXTERNALLY`. Set when the fleet is created and never changed."
          }
        },
        "required": [
          "fleetId",
          "name",
          "status",
          "requestedAt",
          "createdAt",
          "updatedAt",
          "computeType",
          "minimumFootprint",
          "infrastructure",
          "bootstrap"
        ]
      },
      "ListFleetsResponse": {
        "type": "object",
        "description": "Response containing a list of fleets with optional pagination metadata",
        "properties": {
          "fleets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Fleet"
            },
            "description": "Array of fleet objects"
          },
          "nextToken": {
            "type": "string",
            "nullable": true,
            "description": "Pagination token to retrieve the next page of results. Null when pagination not used or no more pages available.",
            "example": "eyJlbmNyeXB0ZWREYXRhIjoiLi4uIn0="
          },
          "limit": {
            "type": "integer",
            "nullable": true,
            "description": "Number of items requested per page. Null when pagination not used.",
            "example": 50,
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": [
          "fleets"
        ]
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Error message",
            "example": "Fleet not found"
          },
          "code": {
            "type": "string",
            "description": "Error code",
            "example": "FLEET_NOT_FOUND"
          },
          "timestamp": {
            "type": "integer",
            "description": "Timestamp when the error occurred (milliseconds since epoch UTC)",
            "example": 1755817319000
          },
          "details": {
            "type": "object",
            "description": "Optional structured detail, e.g. per-field validation errors",
            "additionalProperties": true
          }
        },
        "required": [
          "error",
          "timestamp"
        ]
      },
      "FleetStatus": {
        "type": "string",
        "enum": [
          "ACTIVE",
          "INACTIVE",
          "PROVISIONING",
          "SCALING_UP",
          "SCALING_DOWN",
          "DECOMMISSIONED",
          "TERMINATING",
          "TERMINATED"
        ],
        "description": "Current status of the fleet",
        "example": "ACTIVE"
      },
      "FleetHealthResponse": {
        "type": "object",
        "properties": {
          "fleetId": {
            "type": "string",
            "description": "Unique identifier for the fleet",
            "example": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
          },
          "status": {
            "type": "string",
            "enum": [
              "healthy",
              "unhealthy",
              "degraded",
              "unknown"
            ],
            "description": "Overall health status of the fleet",
            "example": "healthy"
          },
          "kubernetes_health": {
            "type": "object",
            "description": "Legacy managed Kubernetes cluster health information",
            "additionalProperties": true
          },
          "node_health": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NodeHealth"
            },
            "description": "Health information for each node in the fleet"
          }
        },
        "required": [
          "fleetId"
        ]
      },
      "NodeHealth": {
        "type": "object",
        "properties": {
          "nodeId": {
            "type": "string",
            "description": "Unique identifier for the node",
            "example": "node-12345"
          },
          "status": {
            "type": "string",
            "enum": [
              "healthy",
              "unhealthy",
              "degraded",
              "unknown"
            ],
            "description": "Health status of the node",
            "example": "healthy"
          },
          "lastUpdatedAt": {
            "type": "integer",
            "description": "Timestamp when the node health was last updated (milliseconds since epoch UTC)",
            "example": 1755817319000
          }
        },
        "required": [
          "nodeId",
          "status",
          "lastUpdatedAt"
        ]
      },
      "NodeState": {
        "type": "string",
        "description": "Current lifecycle state of a physical / fleet node.",
        "enum": [
          "ACTIVE",
          "BASELINING",
          "CONFIGURING",
          "CONTRACTING",
          "FAILED_PROVISIONING",
          "ONBOARDING",
          "PROVISIONING",
          "READY",
          "TERMINATED",
          "TERMINATING",
          "TESTING",
          "UNHEALTHY",
          "VALIDATION"
        ],
        "example": "ACTIVE"
      },
      "FleetNode": {
        "type": "object",
        "description": "A node within a fleet (fleet_id not included as it's redundant in fleet context)",
        "properties": {
          "nodeName": {
            "type": "string",
            "description": "Unique identifier for the node",
            "example": "g0388"
          },
          "state": {
            "$ref": "#/components/schemas/NodeState"
          },
          "publicIp": {
            "type": "string",
            "description": "Public IP address of the node",
            "example": "10.9.41.182"
          },
          "gpuType": {
            "type": "string",
            "description": "GPU model installed on this node. Not an enum: new hardware models must reach clients rather than break deserialization. Absent when the model is not known.",
            "example": "H200_BM"
          }
        },
        "required": [
          "nodeName",
          "state",
          "publicIp"
        ]
      },
      "Node": {
        "type": "object",
        "description": "A node represents an individual compute instance within a fleet",
        "properties": {
          "nodeName": {
            "type": "string",
            "description": "Unique identifier for the node",
            "example": "g0388"
          },
          "state": {
            "$ref": "#/components/schemas/NodeState"
          },
          "publicIp": {
            "type": "string",
            "description": "Public IP address of the node",
            "example": "10.9.41.182"
          },
          "fleetId": {
            "type": "string",
            "description": "Fleet ID associated with the node, if any",
            "example": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
          },
          "gpuType": {
            "type": "string",
            "description": "GPU model installed on this node. Not an enum: new hardware models must reach clients rather than break deserialization. Absent when the model is not known.",
            "example": "H200_BM"
          }
        },
        "required": [
          "nodeName",
          "state",
          "publicIp"
        ]
      },
      "CreateSSHKeyRequest": {
        "type": "object",
        "required": [
          "username",
          "publicKey"
        ],
        "properties": {
          "username": {
            "type": "string",
            "pattern": "^[a-zA-Z_][a-zA-Z0-9._-]{0,31}$",
            "description": "Linux username (POSIX-compliant). 1-32 chars, starts with letter/underscore.",
            "example": "john_doe"
          },
          "publicKey": {
            "type": "string",
            "description": "SSH public key in any standard format. Will be normalized to OpenSSH format.",
            "example": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl user@example.com"
          },
          "description": {
            "type": "string",
            "maxLength": 256,
            "description": "Optional description for this key (e.g., 'MacBook Pro')",
            "example": "Work laptop"
          }
        }
      },
      "PublicKeyEntry": {
        "type": "object",
        "description": "A single SSH public key with metadata",
        "properties": {
          "fingerprint": {
            "type": "string",
            "description": "SHA256 fingerprint of the public key",
            "example": "SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8"
          },
          "key": {
            "type": "string",
            "description": "SSH public key in OpenSSH format"
          },
          "keyType": {
            "type": "string",
            "enum": [
              "ssh-rsa",
              "ssh-ed25519",
              "ecdsa-sha2-nistp256",
              "ecdsa-sha2-nistp384",
              "ecdsa-sha2-nistp521",
              "sk-ssh-ed25519@openssh.com",
              "sk-ecdsa-sha2-nistp256@openssh.com"
            ],
            "description": "SSH key algorithm type"
          },
          "description": {
            "type": "string",
            "description": "Optional description for this key"
          },
          "addedAt": {
            "type": "integer",
            "format": "int64",
            "description": "When this key was added (Unix milliseconds)"
          }
        }
      },
      "SSHKey": {
        "type": "object",
        "description": "A user's SSH access record with multiple public keys",
        "properties": {
          "sshKeyId": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for this record"
          },
          "username": {
            "type": "string",
            "description": "Linux username for SSH access and cloud-init"
          },
          "publicKeys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicKeyEntry"
            },
            "description": "List of SSH public keys for this user"
          },
          "createdAt": {
            "type": "integer",
            "format": "int64",
            "description": "Creation timestamp (Unix milliseconds)"
          }
        }
      },
      "ModifyStorageRequest": {
        "type": "object",
        "properties": {
          "storageViews": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "mountPoint": {
                  "type": "string",
                  "description": "Mount point for the storage view (e.g., '/data', '/home')",
                  "example": "/data"
                },
                "size": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Storage size in bytes (maximum: 1PB = 1,125,899,906,842,624 bytes)",
                  "example": 536870912000,
                  "minimum": 1,
                  "maximum": 1125899906842624
                }
              },
              "required": [
                "mountPoint",
                "size"
              ]
            },
            "description": "List of storage views to modify. Must match the existing storage configuration: same number of items and same mount points. Only the size values can be changed.",
            "minItems": 1
          }
        },
        "required": [
          "storageViews"
        ]
      },
      "ModifyStorageResponse": {
        "type": "object",
        "properties": {
          "fleetId": {
            "type": "string",
            "description": "Unique identifier for the fleet",
            "example": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
          },
          "status": {
            "type": "string",
            "description": "Status of the storage modification operation",
            "example": "success"
          },
          "message": {
            "type": "string",
            "description": "Descriptive message about the operation",
            "example": "Storage modification request submitted successfully"
          }
        },
        "required": [
          "fleetId",
          "status",
          "message"
        ]
      },
      "NodePowerState": {
        "type": "object",
        "description": "Eventually consistent power state for a node. powerState is the last confirmed value and can lag the hardware while a power operation is in progress, or until the confirmation is older than 5 minutes. lastOperation shows the status of the most recent power operation.",
        "properties": {
          "nodeId": {
            "type": "string",
            "description": "Node identifier.",
            "example": "g311"
          },
          "powerState": {
            "type": "string",
            "description": "Last confirmed power state. Eventually consistent: it can lag the hardware while a power operation is in progress, and it is refreshed from the hardware when the confirmation is older than 5 minutes.",
            "example": "On"
          },
          "lastOperation": {
            "$ref": "#/components/schemas/NodePowerLastOperation"
          }
        },
        "required": [
          "nodeId",
          "powerState"
        ]
      },
      "NodePowerLastOperation": {
        "type": "object",
        "description": "Most recent power operation for the node.",
        "properties": {
          "operationId": {
            "type": "string",
            "description": "Operation identifier."
          },
          "resetType": {
            "type": "string",
            "description": "Reset type requested.",
            "example": "ForceRestart"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACCEPTED",
              "IN_PROGRESS",
              "SUCCESS",
              "FAILURE",
              "TIMED_OUT"
            ],
            "description": "Current operation status. ACCEPTED = request received, execution not started. IN_PROGRESS = execution underway, result not yet known."
          },
          "queuedAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix millis when the operation was queued."
          },
          "completedAt": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Unix millis when the operation completed. Null if non-terminal."
          },
          "error": {
            "$ref": "#/components/schemas/NodePowerOperationError"
          }
        },
        "required": [
          "operationId",
          "resetType",
          "status",
          "queuedAt"
        ]
      },
      "NodePowerOperationError": {
        "type": "object",
        "nullable": true,
        "description": "Error details on FAILURE or TIMED_OUT. Null on success or non-terminal.",
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable error code."
          },
          "message": {
            "type": "string",
            "description": "Human-readable error description."
          },
          "resetIssued": {
            "type": "string",
            "enum": [
              "yes",
              "no",
              "unknown"
            ],
            "description": "Whether the reset command was actually sent to the hardware."
          }
        },
        "required": [
          "code",
          "message",
          "resetIssued"
        ]
      },
      "NodePowerOperation": {
        "type": "object",
        "description": "Requests a power transition on a node. Valid transitions depend on the node's current power state (e.g. `On` is only valid when the node is off). All reset types require the Administrator role.",
        "properties": {
          "resetType": {
            "type": "string",
            "enum": [
              "On",
              "ForceOff",
              "GracefulShutdown",
              "ForceRestart"
            ],
            "description": "Power action to apply. `On` powers the node on. `ForceOff` cuts power immediately and leaves the node off. `GracefulShutdown` requests an OS shutdown and leaves the node off. `ForceRestart` reboots immediately.",
            "example": "ForceRestart"
          }
        },
        "required": [
          "resetType"
        ]
      },
      "NodePowerOperationQueued": {
        "type": "object",
        "description": "Confirmation that a power operation was accepted and queued. The operation is asynchronous - use `operationId` to track operation status via GET.",
        "properties": {
          "nodeId": {
            "type": "string",
            "description": "Node identifier.",
            "example": "g311"
          },
          "resetType": {
            "type": "string",
            "enum": [
              "On",
              "ForceOff",
              "GracefulShutdown",
              "ForceRestart"
            ],
            "description": "Power action that was queued. One of `On`, `ForceOff`, `GracefulShutdown`, or `ForceRestart`.",
            "example": "ForceRestart"
          },
          "powerStateBefore": {
            "type": "string",
            "description": "Live BMC power state read immediately before queueing the operation.",
            "example": "On"
          },
          "status": {
            "type": "string",
            "description": "Queue status for the requested operation.",
            "example": "queued"
          },
          "operationId": {
            "type": "string",
            "description": "Unique identifier for the power operation. Use this to track operation status via GET."
          }
        },
        "required": [
          "nodeId",
          "resetType",
          "powerStateBefore",
          "status",
          "operationId"
        ]
      },
      "StorageView": {
        "type": "object",
        "description": "The API's typed view of a single physical VAST storage view (a mount point and its quotas). Sizes are in bytes; the storage backend wire format is not exposed to callers.",
        "properties": {
          "mountPoint": {
            "type": "string",
            "description": "Mount point for the storage view (e.g., '/data', '/home').",
            "example": "/data"
          },
          "size": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Provisioned size in bytes.",
            "example": 536870912000
          },
          "softLimit": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Soft quota in bytes, when set.",
            "example": 53687091200
          },
          "hardLimit": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Hard quota in bytes, when set.",
            "example": 64424509440
          },
          "state": {
            "type": "string",
            "enum": [
              "provisioning",
              "modifying",
              "active",
              "terminating",
              "unhealthy"
            ],
            "description": "Lifecycle state of the storage view on the backing VAST tenant. Callers should treat `active` as the only \"ready to use\" state; `provisioning` and `modifying` are transient and callers that just issued a 202 add/update should poll `GET .../storage/views/{view}` until `state == \"active\"` (or `unhealthy` to fail fast). The `terminating` state is observable when a delete is in progress or during fleet teardown. The field is optional and will be **absent** from the response for three reasons: (1) the upstream response omitted it (older deployments); (2) the storage backend returned a lifecycle value the API does not recognize (forward-compatibility with future upstream enum members \u2014 the raw value is captured in the API logs); (3) the PATCH refresh-GET failed and the API fell back to a synthesized response body. In all three cases callers should treat an absent `state` as \"unknown, please re-GET\". Additional caveat: on a POST 202 response served via idempotency-key replay, `state` reflects the original request's timepoint (typically `provisioning`), not the current lifecycle state; re-`GET` to obtain authoritative state.",
            "example": "active"
          }
        },
        "required": [
          "mountPoint"
        ]
      },
      "StorageViewListResponse": {
        "type": "object",
        "description": "The set of physical VAST storage views for a fleet's reservation.",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StorageView"
            },
            "description": "Storage views. Empty array (not null) when none are provisioned."
          },
          "storagePending": {
            "type": "boolean",
            "description": "True when the fleet exists but its storage has not been materialized yet; in that case `items` is always empty. Omitted (or false) once storage is available."
          }
        },
        "required": [
          "items"
        ]
      },
      "StorageProtectionPolicy": {
        "type": "object",
        "description": "Optional snapshot protection policy applied when first provisioning a storage view.",
        "properties": {
          "startAt": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 datetime to start the protection policy."
          },
          "every": {
            "type": "string",
            "description": "Snapshot frequency (e.g., '15m' for every 15 minutes)."
          },
          "keepLocal": {
            "type": "string",
            "description": "Duration to keep local snapshots (e.g., '10h')."
          },
          "keepRemote": {
            "type": "string",
            "description": "Duration to keep remote snapshots (e.g., '0s' for none)."
          }
        }
      },
      "AddStorageViewRequest": {
        "type": "object",
        "description": "Request to add a new physical VAST storage view to a fleet's reservation. At least one quota field (`size`, `hardLimit`, or `softLimit`+`hardLimit`) is required. Accepted quota shapes: (1) `size` alone, (2) `hardLimit` alone (treated as an alias for `size`; the soft quota is then set to 90% automatically), or (3) `softLimit`+`hardLimit` together (or `softLimit`+`size`, since `size` and `hardLimit` are aliases). `softLimit` on its own is rejected. If both `size` and `hardLimit` are supplied they must be equal.",
        "properties": {
          "mountPoint": {
            "type": "string",
            "description": "Mount point for the new storage view. One path segment under '/', charset [a-zA-Z0-9_-], max 128 characters.",
            "maxLength": 128,
            "pattern": "^/[a-zA-Z0-9_-]+$",
            "example": "/data"
          },
          "size": {
            "type": "integer",
            "format": "int64",
            "description": "Provisioned size in bytes. Must be a positive multiple of 1 MiB (1048576 bytes). May be supplied on its own (the soft quota is then set to 90% of size automatically); when supplied together with `hardLimit`, the two must be equal.",
            "minimum": 1048576,
            "multipleOf": 1048576,
            "example": 536870912000
          },
          "softLimit": {
            "type": "integer",
            "format": "int64",
            "description": "Soft quota in bytes. Must be a positive multiple of 1 MiB (1048576 bytes) and less than or equal to the hard quota. Must be supplied together with `hardLimit` (or with `size` acting as the hard quota).",
            "minimum": 1048576,
            "multipleOf": 1048576
          },
          "hardLimit": {
            "type": "integer",
            "format": "int64",
            "description": "Hard quota in bytes. Must be a positive multiple of 1 MiB (1048576 bytes). May be supplied on its own (treated as an alias for `size`; the soft quota is then set to 90% automatically) or together with `softLimit`. When supplied together with `size`, the two must be equal.",
            "minimum": 1048576,
            "multipleOf": 1048576
          },
          "protectionPolicy": {
            "$ref": "#/components/schemas/StorageProtectionPolicy"
          },
          "provision": {
            "type": "boolean",
            "default": true,
            "description": "Whether to trigger VAST provisioning after adding the view. Only applies when storage has not yet been provisioned."
          }
        },
        "required": [
          "mountPoint"
        ]
      },
      "UpdateStorageViewRequest": {
        "type": "object",
        "description": "Request to update the size/quotas of an existing physical VAST storage view. The mount point is taken from the URL path. At least one of `size`, `hardLimit`, `softLimit` is required. Accepted quota shapes: (1) `size` alone, (2) `hardLimit` alone (treated as an alias for `size`; the soft quota is then reset to 90% automatically), or (3) `softLimit`+`hardLimit` together (or `softLimit`+`size`, since `size` and `hardLimit` are aliases). `softLimit` on its own is rejected. If both `size` and `hardLimit` are supplied they must be equal.",
        "properties": {
          "size": {
            "type": "integer",
            "format": "int64",
            "description": "New provisioned size in bytes. Must be a positive multiple of 1 MiB (1048576 bytes). May be supplied on its own (resets the soft quota to 90% of size); when supplied together with `hardLimit`, the two must be equal.",
            "minimum": 1048576,
            "multipleOf": 1048576
          },
          "softLimit": {
            "type": "integer",
            "format": "int64",
            "description": "New soft quota in bytes. Must be a positive multiple of 1 MiB (1048576 bytes) and less than or equal to the hard quota. Must be supplied together with `hardLimit` (or with `size` acting as the hard quota).",
            "minimum": 1048576,
            "multipleOf": 1048576
          },
          "hardLimit": {
            "type": "integer",
            "format": "int64",
            "description": "New hard quota in bytes. Must be a positive multiple of 1 MiB (1048576 bytes). May be supplied on its own (treated as an alias for `size`; the soft quota is then reset to 90% automatically) or together with `softLimit`. When supplied together with `size`, the two must be equal.",
            "minimum": 1048576,
            "multipleOf": 1048576
          }
        }
      },
      "AuditLogEntry": {
        "type": "object",
        "description": "A single audit event for an organization: who performed an operation, when, and from where. This is a curated, customer-facing subset of the internal audit record.",
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "When the request completed (RFC 3339 / ISO 8601, UTC)."
          },
          "userId": {
            "type": "string",
            "description": "Identifier of the user (token subject) who made the request, when available."
          },
          "operation": {
            "type": "string",
            "description": "High-level operation name for the request (e.g., LIST_FLEETS, DELETE_FLEET)."
          },
          "method": {
            "type": "string",
            "description": "HTTP method of the request (e.g., GET, POST, DELETE)."
          },
          "route": {
            "type": "string",
            "description": "Matched route template for the request (e.g., 'GET /v1/fleets/{fleetId}')."
          },
          "statusCode": {
            "type": "integer",
            "description": "HTTP status code returned for the request."
          },
          "authOutcome": {
            "type": "string",
            "description": "Authorization outcome for the request (e.g., 'allowed', 'denied', 'unauthenticated')."
          },
          "clientIp": {
            "type": "string",
            "description": "Best-effort client IP address the request originated from, when available."
          },
          "userAgent": {
            "type": "string",
            "description": "User-agent string reported by the client, when available."
          },
          "resource": {
            "type": "string",
            "description": "Concrete resource(s) the request acted on, flattened as comma-separated key=value pairs (e.g. 'fleetId=f-123' or 'fleetId=f-123,nodeId=g001'). Absent when the request targeted no specific resource. Whereas 'route' shows the template, this shows the actual identifiers."
          }
        },
        "required": [
          "timestamp",
          "operation",
          "method",
          "route",
          "statusCode"
        ]
      },
      "AuditLogListResponse": {
        "type": "object",
        "description": "A bounded, newest-first list of recent audit events for the caller's organization.",
        "properties": {
          "items": {
            "type": "array",
            "description": "Recent audit events, newest first. Empty array (not null) when there is no recent activity.",
            "items": {
              "$ref": "#/components/schemas/AuditLogEntry"
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "AuditLogExportStatusResponse": {
        "type": "object",
        "description": "State of the caller's 90-day audit export: which window it covers, whether the archive is ready, and - once it is - a short-lived presigned download URL.",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "notStarted",
              "running",
              "ready",
              "failed"
            ],
            "description": "Where the export stands. 'notStarted': no archive for today's window and nothing running - POST to start one. 'running': a build is in progress, poll again in a few seconds. 'ready': the archive is complete and 'url' is present. 'failed': the build did not finish, see 'error', and POST to retry.\n\n**Which operation returns which:** POST only ever returns 'running' or 'ready' - starting an export always leaves it in one of those two states. All four are possible from GET. 'notStarted' is therefore GET-only, and you will see it when you check before any export has been requested, and again after each UTC midnight, when the previous day's archive no longer covers the current window."
          },
          "windowStart": {
            "type": "string",
            "format": "date-time",
            "description": "Inclusive start of the exported window: a UTC midnight, 90 days before 'windowEnd'."
          },
          "windowEnd": {
            "type": "string",
            "format": "date-time",
            "description": "Exclusive end of the exported window: the most recent UTC midnight. The current partial day is not included."
          },
          "format": {
            "type": "string",
            "enum": [
              "ndjson+gzip"
            ],
            "description": "Archive encoding: gzip-compressed newline-delimited JSON, one audit event per line."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Presigned HTTPS URL for the gzipped NDJSON archive. Present only when 'status' is 'ready'. Treat it as a credential: anyone holding it can download the archive until it expires."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "When 'url' stops working (RFC 3339 / ISO 8601, UTC). Present only when 'status' is 'ready'. Minutes, not hours - call the endpoint again for a fresh URL. The archive itself outlives the URL."
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the current (or most recent) build started. Absent when 'status' is 'notStarted'."
          },
          "completedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the build finished, successfully or not. Present only when 'status' is 'ready' or 'failed'."
          },
          "error": {
            "type": "string",
            "description": "Short, non-sensitive reason the build failed. Present only when 'status' is 'failed'."
          }
        },
        "required": [
          "status",
          "windowStart",
          "windowEnd",
          "format"
        ]
      },
      "FleetHistoryResponse": {
        "type": "object",
        "description": "Response containing fleet history events with optional pagination metadata",
        "properties": {
          "fleetId": {
            "type": "string",
            "description": "Unique identifier for the fleet"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FleetHistoryEvent"
            },
            "description": "List of fleet history events, newest first"
          },
          "nextToken": {
            "type": "string",
            "nullable": true,
            "description": "Pagination token to retrieve the next page of results. Null when no more pages available.",
            "example": "eyJlbmNyeXB0ZWREYXRhIjoiLi4uIn0="
          }
        },
        "required": [
          "fleetId",
          "events"
        ]
      },
      "FleetHistoryEvent": {
        "type": "object",
        "properties": {
          "orgId": {
            "type": "string",
            "description": "Organization ID"
          },
          "fleetId": {
            "type": "string",
            "description": "Fleet ID"
          },
          "source": {
            "type": "string",
            "description": "Source of the event, either `system` or `user`.",
            "enum": [
              "system",
              "user"
            ]
          },
          "currentState": {
            "type": "string",
            "description": "Current state after this event"
          },
          "previousState": {
            "type": "string",
            "description": "Previous state before this event"
          },
          "eventTimestamp": {
            "type": "integer",
            "format": "int64",
            "description": "Timestamp when the event occurred (milliseconds since epoch UTC)"
          },
          "eventData": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Additional event-specific data"
          },
          "createdAt": {
            "type": "integer",
            "format": "int64",
            "description": "Timestamp when the record was created"
          },
          "schemaVersion": {
            "type": "integer",
            "description": "Schema version"
          }
        },
        "required": [
          "orgId",
          "fleetId",
          "source",
          "currentState",
          "eventTimestamp",
          "createdAt",
          "schemaVersion"
        ]
      },
      "ListNodesResponse": {
        "type": "object",
        "description": "Response containing a list of nodes with optional pagination metadata",
        "properties": {
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Node"
            },
            "description": "List of nodes in the fleet"
          },
          "nextToken": {
            "type": "string",
            "nullable": true,
            "description": "Pagination token to retrieve the next page of results. Null when no more pages available.",
            "example": "eyJlbmNyeXB0ZWREYXRhIjoiLi4uIn0="
          },
          "limit": {
            "type": "integer",
            "nullable": true,
            "description": "Number of items requested per page. Null when pagination not used.",
            "example": 100,
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": [
          "nodes"
        ]
      },
      "GrafanaDashboardResponse": {
        "type": "object",
        "description": "Monitoring dashboard information for a fleet. Each dashboard provides real-time metrics and visualizations.",
        "properties": {
          "fleetId": {
            "type": "string",
            "description": "Fleet identifier this dashboard monitors",
            "example": "900e8eac-2b1f-421f-a635-72556268b41f"
          },
          "dashboardId": {
            "type": "string",
            "description": "Dashboard type identifier - different dashboards show different levels of detail",
            "example": "overview"
          },
          "dashboardUrl": {
            "type": "string",
            "format": "uri",
            "description": "Direct link to view this dashboard in Grafana. Users authenticate via Auth0 SSO when opening the link.",
            "example": "https://grafana.sea1.voltagepark.com/d/abc123/fleet-overview"
          },
          "available": {
            "type": "boolean",
            "description": "Indicates if the dashboard can be accessed. `false` means the fleet is not in ACTIVE state or monitoring is temporarily disabled.",
            "example": true
          }
        },
        "required": [
          "fleetId",
          "dashboardId",
          "dashboardUrl",
          "available"
        ]
      },
      "PowerActionReadiness": {
        "type": "object",
        "description": "Advisory readiness for disruptive power actions (ForceOff, GracefulShutdown, ForceRestart, GracefulRestart). Power On from Off is never gated by this object. `ready` means the API found no known blocker; warnings do not change readiness. The policy and user-facing copy are selected by API plane, while machine-readable blocker and warning codes remain internal for structured logging. Clients should not re-derive readiness from registrationStatus, schedulable, taints, or drained.",
        "required": [
          "ready",
          "blockerMessage",
          "warningMessage"
        ],
        "properties": {
          "ready": {
            "type": "boolean",
            "description": "True when the API found no known blocker. A non-empty warningMessage remains advisory and does not change this value."
          },
          "blockerMessage": {
            "type": "string",
            "description": "Empty when ready. Otherwise contains the backend-owned, plane-appropriate explanation for the active blocker. Clients should display this complete sentence without parsing it."
          },
          "warningMessage": {
            "type": "string",
            "description": "Empty when there are no warnings. The API composes active warning messages as complete sentences in deterministic order. Warnings are advisory and do not change ready."
          }
        }
      },
      "NodeManagedServices": {
        "type": "object",
        "description": "Managed-service overlays for this physical node. Omit the entire object when no managed service resolves (e.g. non-Kubernetes fleet or name-lookup miss).",
        "properties": {
          "kubernetes": {
            "$ref": "#/components/schemas/Mks2WorkerNodeDetail",
            "description": "Managed Kubernetes worker-node detail when this node is registered in the fleet's cluster."
          }
        }
      },
      "NodeDetails": {
        "type": "object",
        "description": "Consolidated single-node details for the node-details page. Composes base physical-node fields (publicIp only), advisory powerActionReadiness, and optional managedServices. Power readiness checks cluster join, cordon, and drain state. Existing list/detail endpoints are unchanged.",
        "required": [
          "nodeName",
          "state",
          "publicIp",
          "powerActionReadiness"
        ],
        "properties": {
          "nodeName": {
            "type": "string",
            "description": "Unique identifier for the node (cluster registry id).",
            "example": "g0546"
          },
          "state": {
            "$ref": "#/components/schemas/NodeState"
          },
          "publicIp": {
            "type": "string",
            "description": "Public IP address of the node",
            "example": "159.26.86.38"
          },
          "fleetId": {
            "type": "string",
            "description": "Fleet ID associated with the node, if any",
            "example": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
          },
          "powerActionReadiness": {
            "$ref": "#/components/schemas/PowerActionReadiness",
            "description": "Customer readiness policy. Joined-node blockers use `Before continuing, ensure the node is cordoned and fully drained.`"
          },
          "managedServices": {
            "$ref": "#/components/schemas/NodeManagedServices",
            "description": "Omitted when no managed service resolves."
          }
        }
      },
      "Mks2NodeTaint": {
        "type": "object",
        "description": "A taint on a live Kubernetes node (from the Kubernetes node spec). Identity is key+effect.",
        "required": [
          "key",
          "effect"
        ],
        "properties": {
          "key": {
            "type": "string",
            "description": "Taint key. Maintenance uses voltagepark.io/maintenance.",
            "example": "voltagepark.io/maintenance"
          },
          "value": {
            "type": "string",
            "description": "Optional taint value. For `voltagepark.io/maintenance`, a value written through the managed Kubernetes node-taint API is the hold's end time in Unix seconds, and `true` means no end time.",
            "example": "true"
          },
          "effect": {
            "type": "string",
            "enum": [
              "NoSchedule",
              "PreferNoSchedule"
            ],
            "description": "Taint effect. NoExecute is not exposed on the API write path."
          }
        }
      },
      "Mks2NodeMaintenance": {
        "type": "object",
        "description": "Maintenance state of the node, read from the live Kubernetes node on every request. The `voltagepark.io/maintenance` taint keeps new pods off the node, and the `MaintenanceWindow` node condition pauses Voltage Park's per-node health alerts. Changes made outside this API (kubectl, automation, a hold expiring) show up on the next read.",
        "required": [
          "active"
        ],
        "properties": {
          "active": {
            "type": "boolean",
            "description": "Whether a maintenance taint holds the node now: one is present and either has no end time or ends in the future. An expired taint is reported as inactive even while it waits to be removed."
          },
          "kind": {
            "type": "string",
            "enum": [
              "timed",
              "indefinite",
              "validationHold"
            ],
            "description": "What holds the node. `timed` ends at `until` and is removed automatically after it expires. `indefinite` has no end time and stays until someone removes it, for example a taint applied with `kubectl taint node <node> voltagepark.io/maintenance=true:NoSchedule`. `validationHold` keeps a newly joined node out of service until it passes GPU validation. When the node carries more than one maintenance taint, the one in force is reported, preferring `validationHold`, then `indefinite`, then the `timed` one that ends last. Absent when the node carries no maintenance taint."
          },
          "effect": {
            "type": "string",
            "enum": [
              "NoSchedule",
              "PreferNoSchedule"
            ],
            "description": "Effect of the reported maintenance taint. Absent when the node carries no maintenance taint."
          },
          "until": {
            "type": "string",
            "format": "date-time",
            "description": "When a `timed` hold ends. A time in the past means the hold has expired and is waiting to be removed."
          },
          "alertSuppression": {
            "$ref": "#/components/schemas/Mks2NodeAlertSuppression"
          }
        }
      },
      "Mks2NodeAlertSuppression": {
        "type": "object",
        "description": "The node's `MaintenanceWindow` condition, which pauses Voltage Park's per-node health alerts for the node until `until`. It opens when maintenance is declared through the platform API, closes when that maintenance is ended, and otherwise expires on its own. Absent when the node has no such condition.",
        "required": [
          "active"
        ],
        "properties": {
          "active": {
            "type": "boolean",
            "description": "Whether alerts are paused now: the condition is True and `until` is in the future."
          },
          "reason": {
            "type": "string",
            "description": "Category of the caller that opened the window, as recorded on the node, for example `OnCall` for an on-call engineer.",
            "example": "OnCall"
          },
          "openedBy": {
            "type": "string",
            "description": "Audit identity recorded for the window, as `<service>/<user>` where the user is known."
          },
          "since": {
            "type": "string",
            "format": "date-time",
            "description": "When the window started."
          },
          "until": {
            "type": "string",
            "format": "date-time",
            "description": "When the window ends, or ended."
          }
        }
      },
      "AddFleetSSHKeyRequest": {
        "type": "object",
        "description": "Identifies the already-registered SSH key to apply to the fleet.",
        "properties": {
          "sshKeyId": {
            "type": "string",
            "format": "uuid",
            "description": "Identifier of an SSH key record in the caller's organization. Every public key held by that record is applied."
          }
        },
        "required": [
          "sshKeyId"
        ]
      },
      "AddFleetSSHKeyResponse": {
        "type": "object",
        "description": "Acknowledgement that key propagation was accepted.",
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable outcome of the request."
          },
          "nodeCount": {
            "type": "integer",
            "description": "Number of already-provisioned nodes the keys will be applied to. Zero means the fleet has no running nodes yet and the keys will arrive with cloud-init when its nodes deploy."
          }
        },
        "required": [
          "message",
          "nodeCount"
        ]
      },
      "RemoveFleetSSHKeyResponse": {
        "type": "object",
        "description": "Acknowledgement that key revocation was accepted.",
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable outcome of the request."
          },
          "nodeCount": {
            "type": "integer",
            "description": "Number of already-provisioned nodes the keys will be removed from. Zero means the fleet has no running nodes yet."
          }
        },
        "required": [
          "message",
          "nodeCount"
        ]
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 255,
          "example": "123e4567-e89b-12d3-a456-426614174000"
        },
        "description": "**Idempotency Key for Safe Request Retries**\n\nOptional but **strongly recommended** for all mutation operations (POST, PUT, PATCH, DELETE) to enable safe request retries.\n\n**How It Works:**\n- Provide a unique key when making a request\n- The response is cached for 24 hours, including error responses, except a 5xx from a DELETE or PUT (see TTL below)\n- Retrying with the same key returns the cached response immediately; after an uncached DELETE or PUT 5xx, the request runs again\n- Prevents duplicate operations (e.g., creating the same resource twice for one request)\n\n**Key Requirements:**\n- **You are responsible for ensuring uniqueness** across your requests\n- A key is bound to the organization and to the method and path of the request that first used it; reusing it from another organization or for a different method or path returns `422 Unprocessable Entity`\n- Maximum length: 255 characters\n- Any string format is accepted (UUID v4, ULID, custom identifiers, etc.)\n- Recommended: Use UUID v4 for guaranteed global uniqueness\n\n**Key Generation (Recommended):**\n```javascript\n// UUID v4 - Recommended for guaranteed uniqueness\nconst idempotencyKey = crypto.randomUUID(); // Browser/Node.js 19+\n// OR\nconst idempotencyKey = uuidv4(); // using uuid library\n\n// Alternative: Use your own unique identifier\nconst idempotencyKey = `${userId}-${timestamp}-${nonce}`;\nconst idempotencyKey = `order-${orderId}`; // If order ID is unique\n```\n\n**Retry Guidelines:**\n- **Network timeout/failure**: Retry with the **SAME key** to get cached result\n- **409 Conflict** (concurrent request): Wait 5 seconds, retry with **SAME key**\n- **422 Unprocessable Entity** (key already used with a different body, method, path, or organization): Use a **NEW key**, or resend the original request unchanged\n- **5xx Server Error**: For DELETE and PUT, retrying with the **SAME key** runs the request again. For POST and PATCH, the same key returns the cached error; use a **NEW key** to force a fresh attempt\n\n**Response Behavior:**\n- First request: Processes normally, caches response for 24 hours (except a DELETE or PUT 5xx)\n- Duplicate requests: Returns cached response with original status code; after an uncached DELETE or PUT 5xx, processes the request again\n- Requests in-progress: Returns `409 Conflict` (retry after 5 seconds)\n- Key reuse: Returns `422 Unprocessable Entity` when the key was first used with a different body, method, path, or organization\n\n**TTL (Time-To-Live):**\n- In-progress requests: 5 minutes (crash recovery)\n- Completed/failed requests: 24 hours (response caching; a 5xx from DELETE or PUT releases the key instead, unless the release itself fails)\n- Keys automatically expire and can be reused after TTL\n\n**Best Practices:**\n1. Generate key client-side before making the request\n2. Store the key with your request context for retries\n3. Use a new key for each distinct operation (not per retry)\n4. Use UUID v4 format for guaranteed uniqueness\n5. Maximum length: 255 characters\n\n**Example Usage:**\n```python\nimport time\nimport uuid\nimport requests\n\ndef create_ssh_key_with_retry(ssh_key, max_retries=3):\n    # Generate key once for this operation\n    idempotency_key = str(uuid.uuid4())\n    \n    for attempt in range(max_retries):\n        response = requests.post(\n            'https://api.sea1.voltagepark.com/v1/sshkeys',\n            json=ssh_key,\n            headers={\n                'Authorization': f'Bearer {token}',\n                'Idempotency-Key': idempotency_key # Same key for retries\n            }\n        )\n        \n        if response.status_code == 409: # Concurrent request\n            time.sleep(5) # Wait and retry\n            continue\n        return response # A POST 5xx is cached for this key; check state before retrying with a new key\n    \n    raise Exception('Max retries exceeded')\n```"
      }
    }
  }
}