{
  "openapi": "3.0.3",
  "info": {
    "title": "Universe API",
    "description": "REST and WebSocket API for the Universe orchestrator.\n\n## Authentication\nThe API uses Bearer token authentication. Include your token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\n## Permissions\n- **ALL**: Full access to all endpoints (admin, instance management, config changes, logs)\n- **PUBLIC**: No instance endpoints are public. All instance operations require ALL permission.\n\n## Rate Limiting\nPublic API keys are rate-limited (default: 100 calls per 60 seconds). \nAdmin keys (ALL permission) bypass rate limits entirely.\n\n## WebSocket Endpoints\nWebSocket connections require the same `Authorization: Bearer TOKEN` header during the handshake.\n",
    "version": "1.0.0",
    "contact": {
      "name": "Universe Team"
    }
  },
  "servers": [
    {
      "url": "http://localhost:8080/api",
      "description": "Local development server"
    }
  ],
  "paths": {
    "/ping": {
      "get": {
        "summary": "Health check",
        "description": "Returns basic status information about the Universe node.",
        "operationId": "ping",
        "security": [],
        "responses": {
          "200": {
            "description": "Universe is running",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "ok"
                    },
                    "nodeId": {
                      "type": "string",
                      "example": "node-1"
                    },
                    "clusterName": {
                      "type": "string",
                      "example": "universe-cluster"
                    },
                    "master": {
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/node": {
      "get": {
        "summary": "Get current node information",
        "description": "Returns system statistics and uptime for the current node.",
        "operationId": "getNode",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Node details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "nodeId": {
                      "type": "string"
                    },
                    "uptime": {
                      "type": "string"
                    },
                    "systemStats": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/node/config": {
      "get": {
        "summary": "Get current node configuration",
        "description": "Returns the current node's main configuration ( UniverseMainConfiguration).",
        "operationId": "getNodeConfig",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Node configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UniverseMainConfiguration"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/node/reload": {
      "post": {
        "summary": "Reload node configuration",
        "description": "Reloads the node configuration from disk. (Not fully implemented.)",
        "operationId": "reloadNodeConfig",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Not Implemented"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/cluster/nodes": {
      "get": {
        "summary": "List all cluster nodes",
        "description": "Returns a list of all nodes in the Hazelcast cluster.",
        "operationId": "listNodes",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of nodes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "nodeId": {
                        "type": "string"
                      },
                      "address": {
                        "type": "string"
                      },
                      "master": {
                        "type": "boolean"
                      },
                      "resources": {
                        "$ref": "#/components/schemas/NodeResources"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/cluster/nodes/{id}": {
      "get": {
        "summary": "Get a specific node",
        "description": "Returns detailed information about a cluster node, including its instances.",
        "operationId": "getNodeById",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Node details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "nodeId": {
                      "type": "string"
                    },
                    "address": {
                      "type": "string"
                    },
                    "master": {
                      "type": "boolean"
                    },
                    "instances": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/InstanceInfo"
                      }
                    },
                    "resources": {
                      "$ref": "#/components/schemas/NodeResources"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "summary": "Execute a command on a node",
        "description": "Executes a console command on the specified node.\n- If `id` is the current node: runs locally (not yet implemented)\n- If `id` is a remote node: dispatches via Hazelcast (not yet implemented)\n",
        "operationId": "executeNodeCommand",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClusterCommandRequest"
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "Cannot execute command on local node via API",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Cannot execute command on local node via API"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "501": {
            "description": "Remote node command execution not yet implemented"
          }
        }
      }
    },
    "/instances": {
      "get": {
        "summary": "List all instances",
        "description": "Returns all instances across the cluster (active and stopped).",
        "operationId": "listInstances",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of instances",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InstanceInfo"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "summary": "Create a new instance",
        "description": "Deploys a new instance using the specified configuration.",
        "operationId": "createInstance",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInstanceRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Instance created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceInfo"
                }
              }
            }
          },
          "400": {
            "description": "Invalid configuration name"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/instances/{id}": {
      "get": {
        "summary": "Get instance details",
        "description": "Returns detailed information about an instance.\n\n**Requires ALL permission**: This endpoint requires an API key with ALL permission.\n",
        "operationId": "getInstance",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 6,
              "maxLength": 6
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Instance details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceInfo"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "delete": {
        "summary": "Stop and delete an instance",
        "description": "Stops the instance and removes it from the cluster.",
        "operationId": "deleteInstance",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Instance stopped",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Instance stopped"
                    },
                    "instanceId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/instances/{id}/logs": {
      "get": {
        "summary": "Get instance logs",
        "description": "Returns the most recent log lines for an instance.\nWorks with all runtimes (Docker, K8s, screen, tmux, process).\n\n**Requires ALL permission**: This endpoint requires an API key with ALL permission.\n",
        "operationId": "getInstanceLogs",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lines",
            "in": "query",
            "description": "Number of log lines to return",
            "schema": {
              "type": "integer",
              "default": 100,
              "minimum": 1,
              "maximum": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Log lines",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "totalLines": {
                      "type": "integer"
                    },
                    "instanceId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/instances/{id}/live-log": {
      "get": {
        "summary": "Live log stream (WebSocket)",
        "description": "Opens a WebSocket connection that streams live log output from the instance.\n\n**Requires ALL permission**: This endpoint requires an API key with ALL permission.\n\nConnect with:\n```\nws://host/api/instances/{id}/live-log\nAuthorization: Bearer YOUR_TOKEN\n```\n\nMessages are sent as text frames.\n",
        "operationId": "liveLog",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket connection established"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/instances/{id}/state": {
      "put": {
        "summary": "Update instance state",
        "description": "Updates the state and/or heartbeat timestamp of an instance.",
        "operationId": "updateInstanceState",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateStateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "State updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceInfo"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/instances/{id}/lifecycle": {
      "patch": {
        "summary": "Change instance lifecycle",
        "description": "Controls the lifecycle of an instance:\n- `start`: Start a stopped instance\n- `stop`: Stop a running instance\n- `restart`: Restart the instance\n",
        "operationId": "patchInstanceLifecycle",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "target",
            "in": "query",
            "required": true,
            "description": "Target lifecycle state",
            "schema": {
              "type": "string",
              "enum": [
                "start",
                "stop",
                "restart"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lifecycle changed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "instanceId": {
                      "type": "string"
                    },
                    "target": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid target state or instance not found"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/instances/{id}/execute": {
      "post": {
        "summary": "Execute a command on an instance",
        "description": "Sends a command to the instance's stdin. The command is piped directly\nto the running process (e.g., Minecraft console).\n",
        "operationId": "executeInstanceCommand",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExecuteOnInstanceRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Command dispatched",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Command dispatched"
                    },
                    "instanceId": {
                      "type": "string"
                    },
                    "command": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/configurations": {
      "get": {
        "summary": "List all configurations",
        "description": "Returns all instance configurations.",
        "operationId": "listConfigurations",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of configurations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Configuration"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/configurations/{name}": {
      "get": {
        "summary": "Get a configuration",
        "description": "Returns a specific configuration by name.",
        "operationId": "getConfiguration",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Configuration"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Configuration not found"
          }
        }
      },
      "put": {
        "summary": "Create or update a configuration",
        "description": "Creates or updates an instance configuration.",
        "operationId": "putConfiguration",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Configuration"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Configuration saved"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "delete": {
        "summary": "Delete a configuration",
        "description": "Deletes an instance configuration.",
        "operationId": "deleteConfiguration",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Configuration deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/templates": {
      "get": {
        "summary": "List all templates",
        "description": "Returns all available templates organized by group.",
        "operationId": "listTemplates",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of templates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "group": {
                        "type": "string"
                      },
                      "templates": {
                        "type": "array",
                        "items": {
                          "$ref": "#/components/schemas/Template"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/templates/{group}/{name}": {
      "get": {
        "summary": "Get template details",
        "description": "Returns details about a specific template.",
        "operationId": "getTemplate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Template details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "group": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "path": {
                      "type": "string"
                    },
                    "exists": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/templates/{group}/{name}/files": {
      "get": {
        "summary": "List template files",
        "description": "Returns all files within a local template directory.",
        "operationId": "listTemplateFiles",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of files",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "group": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "files": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/templates/{group}/{name}/files/{path}": {
      "get": {
        "summary": "Get file contents",
        "description": "Returns the contents of a specific file within a template.",
        "operationId": "getTemplateFile",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "path",
            "required": true,
            "description": "Relative file path (e.g. server.properties)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File contents",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "File not found"
          }
        }
      },
      "patch": {
        "summary": "Edit file contents",
        "description": "Updates the contents of a file within a local template.",
        "operationId": "patchTemplateFile",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "path",
            "required": true,
            "description": "Relative file path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "File updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "path": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "summary": "Create new file",
        "description": "Creates a new file within a local template. Fails if the file already exists.\nAccepts any content type (text, binary, images, jars, etc.).\n",
        "operationId": "createTemplateFile",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "path",
            "required": true,
            "description": "Relative file path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "File created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "path": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "description": "File already exists"
          }
        }
      },
      "delete": {
        "summary": "Delete file",
        "description": "Deletes a file within a local template.",
        "operationId": "deleteTemplateFile",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "path",
            "required": true,
            "description": "Relative file path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "path": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/templates/{group}/{name}/export": {
      "post": {
        "summary": "Export template as zip",
        "description": "Exports a local template as a zip file.",
        "operationId": "exportTemplate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Zip file",
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Template not found"
          }
        }
      }
    },
    "/templates/{group}/{name}/import": {
      "post": {
        "summary": "Import template from zip",
        "description": "Imports a template from a zip file, overwriting existing files.",
        "operationId": "importTemplate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/zip": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Import successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "group": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/templates/{group}/{name}/sync": {
      "post": {
        "summary": "Sync template from storage provider",
        "description": "Downloads the latest version of a template from a remote storage provider.",
        "operationId": "syncTemplateFromStorage",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StorageSyncRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sync successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "group": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "storage": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Storage provider not found"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/templates/sync": {
      "post": {
        "summary": "Sync templates across cluster",
        "description": "Dispatches a template sync task to the cluster via Hazelcast.",
        "operationId": "syncTemplates",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TemplateSyncRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sync initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Template sync dispatched"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/commands/execute": {
      "post": {
        "summary": "Execute a console command",
        "description": "Executes a command on the Universe master node's console.\nThe command output is captured and returned in the response.\n",
        "operationId": "executeCommand",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExecuteCommandRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Command output",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "command": {
                      "type": "string"
                    },
                    "output": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/console": {
      "get": {
        "summary": "Interactive console (WebSocket)",
        "description": "Opens an interactive WebSocket console to the Universe master node.\n\nConnect with:\n```\nws://host/api/console\nAuthorization: Bearer YOUR_TOKEN\n```\n\nSend commands as text frames. Responses are streamed back as text frames.\n",
        "operationId": "console",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket connection established"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/metrics": {
      "get": {
        "summary": "Metrics scrape endpoint",
        "description": "Returns metrics in Prometheus exposition format.\nUsed by Prometheus or other monitoring systems.\n",
        "operationId": "getMetrics",
        "security": [],
        "responses": {
          "200": {
            "description": "Prometheus metrics",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "# HELP universe_instances_total Total number of instances\n# TYPE universe_instances_total gauge\nuniverse_instances_total 5\n"
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key token. Generate keys via the console command `key create`.\n\n**Permission Levels:**\n- `ALL`: Full admin access to all endpoints\n- `PUBLIC`: Read-only access to public endpoints\n"
      }
    },
    "schemas": {
      "InstanceInfo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique 6-character instance ID",
            "example": "a1b2c3"
          },
          "configurationName": {
            "type": "string",
            "description": "Name of the configuration this instance uses",
            "example": "lobby"
          },
          "wrapperNodeId": {
            "type": "string",
            "description": "ID of the node hosting this instance",
            "example": "node-1"
          },
          "hostAddress": {
            "type": "string",
            "description": "Host address clients should connect to",
            "example": "127.0.0.1"
          },
          "allocatedPort": {
            "type": "integer",
            "description": "Port allocated for this instance",
            "example": 25565
          },
          "state": {
            "$ref": "#/components/schemas/InstanceState"
          },
          "lastHeartbeat": {
            "type": "integer",
            "format": "int64",
            "description": "Unix timestamp of last heartbeat"
          },
          "processPid": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Process ID (null for container runtimes)"
          },
          "allocatedRamMB": {
            "type": "integer",
            "description": "Allocated RAM in MB",
            "example": 2048
          },
          "allocatedCpu": {
            "type": "integer",
            "description": "Allocated CPU units (100 = 1 core)",
            "example": 100
          },
          "runtime": {
            "type": "string",
            "description": "Runtime provider used (screen, docker, k8s, etc.)",
            "example": "docker"
          }
        }
      },
      "InstanceState": {
        "type": "string",
        "enum": [
          "CREATING",
          "ONLINE",
          "OFFLINE",
          "STOPPED"
        ],
        "description": "- **CREATING**: Instance is being deployed\n- **ONLINE**: Instance is running and healthy\n- **OFFLINE**: Instance has missed heartbeats\n- **STOPPED**: Instance has been stopped\n"
      },
      "Configuration": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Unique configuration name",
            "example": "lobby"
          },
          "runtime": {
            "type": "string",
            "description": "Runtime provider key",
            "example": "docker",
            "default": "screen"
          },
          "command": {
            "type": "string",
            "description": "Command to start the instance",
            "example": "java -Xmx2048M -jar server.jar"
          },
          "static": {
            "type": "boolean",
            "description": "Whether this is a static (persistent) instance",
            "default": false
          },
          "ramMB": {
            "type": "integer",
            "description": "RAM allocated in MB",
            "example": 2048,
            "default": 2048
          },
          "cpu": {
            "type": "integer",
            "description": "CPU units (100 = 1 core)",
            "example": 100,
            "default": 100
          },
          "instanceGroups": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Groups this configuration belongs to",
            "example": [
              "lobby"
            ]
          },
          "nodes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Nodes allowed to host this instance",
            "example": [
              "node-1"
            ]
          },
          "hostAddress": {
            "type": "string",
            "description": "Host address for client connections",
            "example": "127.0.0.1"
          },
          "availablePorts": {
            "$ref": "#/components/schemas/PortRange"
          },
          "minimumServiceCount": {
            "type": "integer",
            "description": "Minimum number of instances to maintain",
            "example": 1,
            "default": 1
          },
          "environmentVariables": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Environment variables for the instance",
            "example": {
              "UNIVERSE_INSTANCE_ID": "%INSTANCE_ID%"
            }
          },
          "templateInstallationConfig": {
            "$ref": "#/components/schemas/TemplateInstallationConfig"
          },
          "fileModifications": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Files to modify after template installation",
            "example": [
              "server.properties"
            ]
          },
          "properties": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Additional configuration properties"
          }
        }
      },
      "PortRange": {
        "type": "object",
        "properties": {
          "min": {
            "type": "integer",
            "description": "Minimum port number",
            "example": 25565
          },
          "max": {
            "type": "integer",
            "description": "Maximum port number",
            "example": 25570
          }
        }
      },
      "TemplateInstallationConfig": {
        "type": "object",
        "properties": {
          "allOf": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Template"
            },
            "description": "Templates to install (all required)"
          },
          "allInGroups": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Template groups to install entirely"
          },
          "oneOf": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Template"
            },
            "description": "Templates to choose one from"
          },
          "oneInGroups": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Template groups to choose one template from"
          },
          "onTemplatePasteOverridePresentFiles": {
            "type": "boolean",
            "description": "Whether templates override existing files",
            "default": false
          }
        }
      },
      "Template": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "server"
          },
          "group": {
            "type": "string",
            "example": "default"
          },
          "storage": {
            "type": "string",
            "description": "Storage backend (local, s3)",
            "example": "local"
          },
          "priority": {
            "type": "integer",
            "description": "Installation priority order",
            "example": 1
          }
        }
      },
      "NodeResources": {
        "type": "object",
        "properties": {
          "usedRamMB": {
            "type": "integer",
            "description": "Currently used RAM in MB"
          },
          "usedCpu": {
            "type": "integer",
            "description": "Currently used CPU units"
          }
        }
      },
      "UniverseMainConfiguration": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "example": "127.0.0.1"
          },
          "port": {
            "type": "integer",
            "description": "Hazelcast cluster port",
            "example": 6000
          },
          "apiPort": {
            "type": "integer",
            "description": "REST API port",
            "example": 7000
          },
          "nodeId": {
            "type": "string",
            "example": "node-1"
          },
          "clusterName": {
            "type": "string",
            "example": "universe-cluster"
          },
          "isMasterNode": {
            "type": "boolean"
          },
          "masterAddress": {
            "type": "string"
          },
          "masterPort": {
            "type": "integer"
          },
          "masterApiPort": {
            "type": "integer"
          },
          "debug": {
            "type": "boolean"
          },
          "maxRamMB": {
            "type": "integer"
          },
          "maxCpu": {
            "type": "integer"
          }
        }
      },
      "CreateInstanceRequest": {
        "type": "object",
        "properties": {
          "configurationName": {
            "type": "string",
            "description": "Name of the configuration to use",
            "example": "lobby"
          }
        },
        "required": [
          "configurationName"
        ]
      },
      "UpdateStateRequest": {
        "type": "object",
        "properties": {
          "state": {
            "type": "string",
            "description": "New state value",
            "enum": [
              "CREATING",
              "ONLINE",
              "OFFLINE",
              "STOPPED"
            ]
          },
          "lastHeartbeat": {
            "type": "integer",
            "format": "int64",
            "description": "Unix timestamp (optional, resets if not provided)"
          }
        },
        "required": [
          "state"
        ]
      },
      "ExecuteOnInstanceRequest": {
        "type": "object",
        "properties": {
          "command": {
            "type": "string",
            "description": "Command to execute on the instance",
            "example": "op andyreckt"
          }
        },
        "required": [
          "command"
        ]
      },
      "ClusterCommandRequest": {
        "type": "object",
        "properties": {
          "command": {
            "type": "string",
            "description": "Console command to execute",
            "example": "instance list"
          }
        },
        "required": [
          "command"
        ]
      },
      "TemplateSyncRequest": {
        "type": "object",
        "properties": {
          "pattern": {
            "type": "string",
            "description": "Template pattern to sync (e.g., default/*, group/name)",
            "example": "default/*"
          }
        },
        "required": [
          "pattern"
        ]
      },
      "StorageSyncRequest": {
        "type": "object",
        "properties": {
          "storage": {
            "type": "string",
            "description": "Storage provider key (e.g. s3, ftp)",
            "example": "s3"
          }
        },
        "required": [
          "storage"
        ]
      },
      "ExecuteCommandRequest": {
        "type": "object",
        "properties": {
          "command": {
            "type": "string",
            "description": "Console command to execute on the master node",
            "example": "help"
          }
        },
        "required": [
          "command"
        ]
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid Authorization header",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "example": "Unauthorized"
                }
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "example": "Rate limit exceeded. Retry after 45000ms."
                },
                "retryAfterMs": {
                  "type": "integer",
                  "example": 45000
                }
              }
            }
          }
        }
      }
    }
  }
}