{
  "openapi": "3.0.3",
  "info": {
    "title": "VLibras Widget — Servidor de Distribuição",
    "description": "API HTTP do servidor que distribui o widget de acessibilidade VLibras (bundle do plugin + runtime Unity WebGL) para sites de terceiros. É um servidor estático e público: expõe healthcheck, a própria especificação OpenAPI e os assets do widget. A tradução de texto em LIBRAS e o dicionário de sinais são serviços externos (traducao2/dicionario2.vlibras.gov.br) consumidos pelo cliente e não fazem parte desta API.",
    "version": "6.0.0",
    "contact": {
      "name": "LAVID — Laboratório de Aplicações de Vídeo Digital (UFPB)",
      "url": "https://www.vlibras.gov.br"
    },
    "license": {
      "name": "LGPL-3.0-or-later",
      "url": "https://www.gnu.org/licenses/lgpl-3.0.html"
    }
  },
  "servers": [
    {
      "url": "http://localhost:8080",
      "description": "Servidor atual (resolvido pelo Host da requisição)"
    },
    {
      "url": "https://www.vlibras.gov.br",
      "description": "CDN oficial de produção do VLibras"
    }
  ],
  "tags": [
    {
      "name": "Health",
      "description": "Verificação de disponibilidade do servidor."
    },
    {
      "name": "Documentation",
      "description": "Especificação OpenAPI, Swagger UI e página inicial."
    },
    {
      "name": "Widget Assets",
      "description": "Bundle do plugin e assets estáticos do runtime Unity WebGL."
    }
  ],
  "paths": {
    "/healthz": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Healthcheck do servidor",
        "description": "Retorna 200 com o corpo \"ok\" quando o servidor está ativo. Usado pelo healthcheck do Docker/nginx.",
        "responses": {
          "200": {
            "description": "Servidor disponível.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "ok\n"
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": [
          "Documentation"
        ],
        "summary": "Especificação OpenAPI desta API",
        "description": "Retorna este documento OpenAPI em JSON. URL estável para importação no Apidog. Disponível em todos os ambientes.",
        "responses": {
          "200": {
            "description": "Documento OpenAPI 3.0.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/docs": {
      "get": {
        "tags": [
          "Documentation"
        ],
        "summary": "Swagger UI (somente fora de produção)",
        "description": "Documentação visual via Swagger UI. Habilitada apenas quando NODE_ENV !== \"production\"; em produção retorna 404 — o schema em /openapi.json permanece acessível.",
        "responses": {
          "200": {
            "description": "Página HTML do Swagger UI.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "Not Found"
              }
            }
          }
        }
      }
    },
    "/": {
      "get": {
        "tags": [
          "Documentation"
        ],
        "summary": "Página inicial com instruções de uso",
        "description": "Página HTML estática com exemplos de uso do widget.",
        "responses": {
          "200": {
            "description": "Página inicial.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/app/vlibras-plugin.js": {
      "get": {
        "tags": [
          "Widget Assets"
        ],
        "summary": "Bundle principal do plugin VLibras",
        "description": "JavaScript do widget, carregado via <script> nas páginas que integram o VLibras.",
        "responses": {
          "200": {
            "description": "Bundle JavaScript do plugin.",
            "content": {
              "text/javascript": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "Not Found"
              }
            }
          }
        }
      }
    },
    "/app/{filepath}": {
      "get": {
        "tags": [
          "Widget Assets"
        ],
        "summary": "Servir asset estático do widget",
        "description": "Serve qualquer arquivo do bundle do widget: JS, runtime Unity WebGL (.wasm/.data), fontes (.woff2), imagens e CSS. Protegido contra path traversal.",
        "parameters": [
          {
            "name": "filepath",
            "in": "path",
            "required": true,
            "description": "Caminho relativo do asset dentro de /app.",
            "schema": {
              "type": "string"
            },
            "example": "vlibras-plugin.js"
          }
        ],
        "responses": {
          "200": {
            "description": "Conteúdo do asset solicitado.",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "URL malformada (sequência percent-encoded inválida).",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "Bad Request"
              }
            }
          },
          "403": {
            "description": "Tentativa de path traversal — caminho fora do diretório base.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "Forbidden"
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "Not Found"
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "BadRequest": {
        "description": "URL malformada (sequência percent-encoded inválida).",
        "content": {
          "text/plain": {
            "schema": {
              "type": "string"
            },
            "example": "Bad Request"
          }
        }
      },
      "Forbidden": {
        "description": "Tentativa de path traversal — caminho fora do diretório base.",
        "content": {
          "text/plain": {
            "schema": {
              "type": "string"
            },
            "example": "Forbidden"
          }
        }
      },
      "NotFound": {
        "description": "Recurso não encontrado.",
        "content": {
          "text/plain": {
            "schema": {
              "type": "string"
            },
            "example": "Not Found"
          }
        }
      }
    }
  }
}
