{
  "openapi": "3.0.3",
  "info": {
    "title": "Aleph HTTP API",
    "version": "1.0.0",
    "description": "HTTP endpoints exposed by the Aleph server."
  },
  "servers": [
    {
      "url": "https://aleph.kotharcomputing.com"
    }
  ],
  "paths": {
    "/openapi.json": {
      "get": {
        "summary": "OpenAPI specification",
        "responses": {
          "200": {
            "description": "OpenAPI document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/version": {
      "get": {
        "summary": "Aleph version",
        "responses": {
          "200": {
            "description": "Current Aleph version",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/analyze": {
      "post": {
        "summary": "Analyze Aleph source",
        "parameters": [
          {
            "name": "include_ast",
            "in": "query",
            "description": "Include a serialized AST when set to true.",
            "schema": {
              "type": "string",
              "enum": ["true", "false"],
              "default": "false"
            }
          },
          {
            "name": "filter_ast",
            "in": "query",
            "description": "Percent-encoded JSON AST filter. When provided, AST output is enabled automatically and `ast` contains matched subtrees. Clauses may constrain immediate child structure with `children.any`.",
            "schema": {
              "type": "string"
            },
            "example": "%7B%22any%22%3A%5B%7B%22types%22%3A%5B%22Fun_Call%22%5D%2C%22children%22%3A%7B%22any%22%3A%5B%7B%22types%22%3A%5B%22Id%22%5D%2C%22text%22%3A%7B%22pattern%22%3A%22%5Efoo%24%22%2C%22mode%22%3A%22regex%22%7D%7D%5D%7D%7D%5D%7D"
          },
          {
            "name": "format",
            "in": "query",
            "description": "Include formatted source in the response when set to true.",
            "schema": {
              "type": "string",
              "enum": ["true", "false"],
              "default": "false"
            }
          },
          {
            "name": "discover_test",
            "in": "query",
            "description": "Include static integrated-test discovery under the `tests` response key when set to true.",
            "schema": {
              "type": "string",
              "enum": ["true", "false"],
              "default": "false"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-aleph": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Analysis result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyzeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/tests/discover": {
      "post": {
        "summary": "Discover integrated Aleph tests",
        "description": "Parse Aleph source and return the static integrated-test tree without evaluating test bodies, cases, options, hooks, includes, or top-level executable code.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-aleph": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Static integrated-test discovery tree",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestDiscoverySection"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/format": {
      "post": {
        "summary": "Format Aleph source",
        "parameters": [
          {
            "name": "tab_size",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 2
            }
          },
          {
            "name": "insert_spaces",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["true", "false"],
              "default": "true"
            }
          },
          {
            "name": "trim_trailing_whitespace",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["true", "false"],
              "default": "false"
            }
          },
          {
            "name": "insert_final_newline",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["true", "false"],
              "default": "false"
            }
          },
          {
            "name": "trim_final_newlines",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["true", "false"],
              "default": "false"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-aleph": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Formatted Aleph source",
            "content": {
              "application/x-aleph": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "BadRequest": {
        "description": "Malformed query parameter",
        "content": {
          "text/plain": {
            "schema": {
              "$ref": "#/components/schemas/TextError"
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "HTTP method is not allowed for this endpoint",
        "content": {
          "text/plain": {
            "schema": {
              "$ref": "#/components/schemas/TextError"
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "Content-Type must be application/x-aleph",
        "content": {
          "text/plain": {
            "schema": {
              "$ref": "#/components/schemas/TextError"
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Internal server error",
        "content": {
          "text/plain": {
            "schema": {
              "$ref": "#/components/schemas/TextError"
            }
          }
        }
      }
    },
    "schemas": {
      "TextError": {
        "type": "string"
      },
      "VersionResponse": {
        "type": "object",
        "required": ["version"],
        "properties": {
          "version": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "AnalyzeResponse": {
        "type": "object",
        "required": ["diagnostics"],
        "properties": {
          "diagnostics": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Diagnostic"
            }
          },
          "ast": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AstNode"
            }
          },
          "format": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "error": {
            "type": "string"
          },
          "tests": {
            "$ref": "#/components/schemas/TestDiscoverySection"
          }
        },
        "additionalProperties": false
      },
      "TestDiscoverySection": {
        "type": "object",
        "required": ["name", "fullName", "file", "location", "sections", "tests"],
        "properties": {
          "name": {
            "type": "string"
          },
          "fullName": {
            "type": "string"
          },
          "file": {
            "type": "string"
          },
          "location": {
            "$ref": "#/components/schemas/TestDiscoveryLocation"
          },
          "sections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TestDiscoverySection"
            }
          },
          "tests": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TestDiscoveryTest"
            }
          }
        },
        "additionalProperties": false
      },
      "TestDiscoveryTest": {
        "type": "object",
        "required": ["name", "fullName", "file", "parameterized", "hasOptions", "location"],
        "properties": {
          "name": {
            "type": "string"
          },
          "fullName": {
            "type": "string"
          },
          "file": {
            "type": "string"
          },
          "parameterized": {
            "type": "boolean"
          },
          "hasOptions": {
            "type": "boolean"
          },
          "location": {
            "$ref": "#/components/schemas/TestDiscoveryLocation"
          }
        },
        "additionalProperties": false
      },
      "TestDiscoveryLocation": {
        "type": "object",
        "required": ["file", "line", "column"],
        "properties": {
          "file": {
            "type": "string"
          },
          "line": {
            "type": "integer",
            "minimum": 0
          },
          "column": {
            "type": "integer",
            "minimum": 0
          }
        },
        "additionalProperties": false
      },
      "Diagnostic": {
        "type": "object",
        "required": ["range", "message"],
        "properties": {
          "range": {
            "$ref": "#/components/schemas/Range"
          },
          "message": {
            "type": "string"
          },
          "severity": {
            "type": "integer",
            "enum": [1, 2, 3, 4],
            "description": "LSP DiagnosticSeverity: 1 error, 2 warning, 3 information, 4 hint."
          },
          "code": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "type": "string"
              }
            ]
          },
          "source": {
            "type": "string"
          }
        }
      },
      "Range": {
        "type": "object",
        "required": ["start", "end"],
        "properties": {
          "start": {
            "$ref": "#/components/schemas/Position"
          },
          "end": {
            "$ref": "#/components/schemas/Position"
          }
        },
        "additionalProperties": false
      },
      "Position": {
        "type": "object",
        "required": ["line", "character"],
        "properties": {
          "line": {
            "type": "integer",
            "minimum": 0
          },
          "character": {
            "type": "integer",
            "minimum": 0
          }
        },
        "additionalProperties": false
      },
      "AstNode": {
        "type": "object",
        "required": ["type", "location"],
        "properties": {
          "type": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "isSynthetic": {
            "type": "boolean",
            "enum": [true]
          },
          "location": {
            "$ref": "#/components/schemas/AstLocation"
          },
          "children": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AstNode"
            }
          }
        }
      },
      "AstLocation": {
        "type": "object",
        "required": ["range"],
        "properties": {
          "uri": {
            "type": "string"
          },
          "range": {
            "$ref": "#/components/schemas/Range"
          }
        },
        "additionalProperties": false
      }
    }
  }
}