docs: redesign do README (padrão TwitterBR-MOD) — dados atualizados
This commit is contained in:
1 parent
7710be86a6
commit
6766c27ca3
1 file changed
+166
@@ -0,0 +1,166 @@
|
||||
<div align="center">
|
||||
|
||||
# OllaHubBackend
|
||||
|
||||
**API HTTP + WebSocket em Rust (Actix Web) para gerenciar o Ollama: verifica e instala o Ollama, lista e baixa
|
||||
modelos, faz chat com streaming e oferece criptografia AES-256-GCM, com JWT e Swagger UI.**
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
[Endpoints](#endpoints) · [Como funciona](#como-funciona) · [Configuração](#configura%C3%A7%C3%A3o) · [Executar](#executar-localmente) · [Limitações](#limita%C3%A7%C3%B5es-conhecidas)
|
||||
|
||||
</div>
|
||||
|
||||
> [!NOTE]
|
||||
> **Estado do projeto:** versão `0.1.0` (`Cargo.toml`), com 3 commits entre 2025-11-05 e 2025-11-18 — estrutura
|
||||
> inicial com API v2 modular, WebSocket, serviços de instalação do Ollama e documentação. A referência completa
|
||||
> dos endpoints está em [`docs/API.md`](docs/API.md) e exemplos de cliente em
|
||||
> [`docs/API_EXAMPLES.md`](docs/API_EXAMPLES.md).
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Nem toda rota exige JWT.** O middleware só protege `/api/v1/*`, `/v2/api/crypto*` e `/v2/api/models*`.
|
||||
> Ficam **públicas** — inclusive `POST /v2/api/ollama/install`, que baixa e executa o instalador do Ollama —
|
||||
> `/health`, `/v2/health`, `/v2/api/ollama/*`, `/docs` e os WebSockets `/v2/ws*`. Por padrão o servidor escuta
|
||||
> só em `127.0.0.1`; defina `JWT_SECRET` com um valor próprio (o padrão é `changeme-dev-secret`) e só mude
|
||||
> `HOST` sabendo disso.
|
||||
|
||||
## Endpoints
|
||||
|
||||
Base URL padrão: `http://127.0.0.1:8080`. Swagger UI em `/docs` (OpenAPI em `/api-doc/openapi.json`).
|
||||
|
||||
| Método | Rota | JWT | O que faz |
|
||||
|---|---|:-:|---|
|
||||
| GET | `/health` | não | Resposta simples `"ok"` |
|
||||
| GET | `/v2/health` | não | `{"status":"ok"}` |
|
||||
| GET | `/v2/api/ollama/check` | não | Estado do Ollama: no `PATH`, versão, API alcançável (`reachable` / `unreachable` / `degraded`), problemas encontrados |
|
||||
| POST | `/v2/api/ollama/install` | não | `202` com `operation_id`; instala em background e espera a API responder (até 60 s) |
|
||||
| GET | `/v2/api/models` | sim | Lista de modelos lida do `modelList.json` |
|
||||
| POST | `/v2/api/models/install` | sim | `202`; baixa o modelo (`{"name": "..."}`) em background via `/api/pull` do Ollama |
|
||||
| POST | `/v2/api/crypto/set-key` | sim | Define a chave AES-256 (`{"hex_key": "<64 hex>"}`) e a grava em disco |
|
||||
| POST | `/v2/api/crypto/rotate-key` | sim | Gera uma chave nova e a devolve em hex |
|
||||
| POST | `/v2/api/crypto/encrypt` | sim | `{"data": "texto"}` → `{"ciphertext": "<base64>"}` |
|
||||
| POST | `/v2/api/crypto/decrypt` | sim | `{"data": "<base64>"}` → `{"plaintext": "texto"}` |
|
||||
| GET/POST | `/api/v1/users` | sim | Lista / cria usuário (nome ≥ 2 caracteres, e-mail válido) |
|
||||
| GET/PUT/DELETE | `/api/v1/users/{id}` | sim | Lê / atualiza / remove usuário |
|
||||
| WS | `/v2/ws` | não | Eco de mensagens e pong; veja [Limitações](#limita%C3%A7%C3%B5es-conhecidas) |
|
||||
| WS | `/v2/ws/chat` | não | Chat com um modelo do Ollama (abaixo) |
|
||||
|
||||
Autenticação: `Authorization: Bearer <jwt>`, assinado em HS256 com `JWT_SECRET`, com as claims `sub` e `exp`
|
||||
(e `role` opcional). **A API não emite tokens** — o segredo precisa ser o mesmo do serviço que os emite (o
|
||||
`.env.example` indica o frontend).
|
||||
|
||||
### Chat por WebSocket (`/v2/ws/chat`)
|
||||
|
||||
Envie um JSON por mensagem de texto:
|
||||
|
||||
```json
|
||||
{ "model": "llama3.2", "messages": [{ "role": "user", "content": "Olá" }], "options": { "temperature": 0.7 } }
|
||||
```
|
||||
|
||||
O servidor responde com mensagens de status — `{"status":"checking"}`, `ready`, `installing` (com `progress`),
|
||||
`installed` — e então as linhas JSON do `/api/chat` do Ollama. **Se o modelo não estiver instalado, ele é baixado
|
||||
antes de responder.** Falhas chegam como `{"error": "...", "done": true}`. Há ping a cada 5 s e a conexão é
|
||||
encerrada após 30 s sem atividade do cliente.
|
||||
|
||||
## Como funciona
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
C["Cliente<br/>OllaHub · curl"] -- "HTTP + JWT" --> S["Actix Web<br/>CORS · logging · JWT"]
|
||||
C -- WebSocket --> S
|
||||
S --> V1["/api/v1/users<br/>repositório em memória"]
|
||||
S --> V2["/v2/api/*<br/>models · ollama · crypto"]
|
||||
S --> WS["/v2/ws · /v2/ws/chat"]
|
||||
V2 --> OL["Ollama :11434<br/>/api/tags · /api/pull · /api/chat"]
|
||||
WS --> OL
|
||||
V2 --> K["crypto_v2.key<br/>AES-256-GCM"]
|
||||
S --> D["/docs<br/>Swagger UI"]
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Módulos e detalhes técnicos</summary>
|
||||
|
||||
| Módulo | Papel |
|
||||
|---|---|
|
||||
| `src/main.rs`, `src/config.rs`, `src/state.rs` | Boot do servidor, configuração por variáveis de ambiente e `AppContext` (broker de eventos, criptografia, URL do Ollama, caminho do `modelList.json`, segredo JWT) |
|
||||
| `src/routes/`, `src/controllers/`, `src/services/user_service.rs`, `src/repositories/`, `src/models/` | CRUD de usuários (`/api/v1`) com documentação OpenAPI (utoipa) |
|
||||
| `src/api/` | Rotas v2: saúde, modelos, Ollama e criptografia |
|
||||
| `src/core/models.rs` | Lê o `modelList.json` (objeto com `models` ou array), verifica modelos instalados (`/api/tags`) e baixa modelos (`/api/pull`) |
|
||||
| `src/services/ollama_install.rs`, `src/services/install/` | Verificação e instalação do Ollama por sistema: Windows (baixa `OllamaSetup.exe` e roda `/silent`), Linux (`curl -fsSL https://ollama.com/install.sh \| sh`), macOS (baixa o zip e extrai em `/Applications`) |
|
||||
| `src/crypto/` | AES-256-GCM com nonce aleatório de 12 bytes prefixado ao ciphertext; chave em hex em `<config do usuário>/OllaHubBackend/crypto_v2.key`, carregada na inicialização |
|
||||
| `src/ws/` | WebSocket de eventos (`/ws`) e de chat (`/ws/chat`), montados sob o escopo `/v2` |
|
||||
| `src/middlewares/` | JWT, CORS (origem única de `ALLOWED_ORIGINS`), logging de requisições e erros padronizados (`{"error": "..."}`) |
|
||||
| `src/services/windows_permissions.rs` | Só no Windows: configuração de permissões na inicialização (veja o aviso abaixo) |
|
||||
| `modelList.json` | Catálogo com 93 modelos (nome, descrição, capacidades, tamanhos, URL na biblioteca do Ollama); a API expõe `name` e `description` |
|
||||
</details>
|
||||
|
||||
> [!WARNING]
|
||||
> **No Windows, o servidor mexe na configuração da máquina ao iniciar.** Se estiver elevado (administrador), ele
|
||||
> cria regras de entrada no Firewall para as portas `8080` e `11434` (perfis Domain, Private e Public) e adiciona
|
||||
> uma exclusão do Windows Defender para o próprio executável (`Add-MpPreference`). Sem privilégios de
|
||||
> administrador apenas registra os avisos e segue.
|
||||
|
||||
## Configuração
|
||||
|
||||
Copie `.env.example` para `.env` (carregado com `dotenv` na inicialização). Todas as variáveis são lidas em
|
||||
`src/config.rs` e `src/middlewares/`:
|
||||
|
||||
| Variável | Padrão | Uso |
|
||||
|---|---|---|
|
||||
| `HOST` | `127.0.0.1` | Endereço de escuta |
|
||||
| `PORT` | `8080` | Porta de escuta |
|
||||
| `OLLAMA_BASE_URL` | `http://localhost:11434` | API do Ollama |
|
||||
| `MODEL_LIST_PATH` | `modelList.json` | Catálogo exposto em `/v2/api/models` |
|
||||
| `JWT_SECRET` | `changeme-dev-secret` | Segredo HS256 — **troque**; deve ser o mesmo de quem emite os tokens |
|
||||
| `ALLOWED_ORIGINS` | `http://localhost:3000` | Única origem aceita pelo CORS (com credenciais) |
|
||||
|
||||
## Executar localmente
|
||||
|
||||
Requisitos: toolchain Rust (edição 2021) e um [Ollama](https://ollama.com) acessível — ou use
|
||||
`POST /v2/api/ollama/install`.
|
||||
|
||||
```bash
|
||||
git clone https://git.evandro.dev.br/evandro/OllaHubBackend.git
|
||||
cd OllaHubBackend
|
||||
cp .env.example .env # ajuste JWT_SECRET e ALLOWED_ORIGINS
|
||||
cargo run # sobe em http://127.0.0.1:8080
|
||||
```
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8080/health
|
||||
curl http://127.0.0.1:8080/v2/api/ollama/check
|
||||
curl -H "Authorization: Bearer <jwt>" http://127.0.0.1:8080/v2/api/models
|
||||
```
|
||||
|
||||
```bash
|
||||
cargo build --release # binário em target/release
|
||||
cargo test # o repositório tem um teste: ida e volta da criptografia
|
||||
```
|
||||
|
||||
## Limitações conhecidas
|
||||
|
||||
- **Usuários só em memória:** o CRUD de `/api/v1/users` usa um repositório em memória; os dados somem ao
|
||||
reiniciar.
|
||||
- **`/v2/ws` não envia eventos:** o endpoint apenas ecoa mensagens e responde a pings. O envio de eventos ao
|
||||
cliente (`PushEvent`) existe no código mas nunca é acionado, e o progresso de instalações vai para outro
|
||||
broker.
|
||||
- **Chat sem streaming incremental:** o corpo da resposta do Ollama é lido por inteiro (timeout de 300 s) antes
|
||||
de as linhas serem repassadas, então os chunks chegam juntos ao fim da geração.
|
||||
- **Downloads sem progresso em tempo real:** `pull_model` também lê a resposta inteira e só depois publica as
|
||||
linhas e o evento final.
|
||||
- **Instalação do Ollama:** roda instaladores baixados da internet no sistema operacional atual
|
||||
(Windows/Linux/macOS); sistemas não suportados retornam erro.
|
||||
- **Documentação defasada em um ponto:** [`docs/OLLAMA.md`](docs/OLLAMA.md) cita rotas legadas
|
||||
(`/ollama/install-check`, `/ollama/install`) — as rotas atuais são `/v2/api/ollama/check` e
|
||||
`/v2/api/ollama/install`.
|
||||
- **`SKIP_ANTIVIRUS_WARNINGS`:** consta no `.env.example`, mas nenhum código lê essa variável.
|
||||
- **Firewall fixo na porta 8080:** a regra criada no Windows usa `8080` literal, mesmo com `PORT` diferente.
|
||||
|
||||
## Avisos
|
||||
|
||||
- Licença: GPL-3.0 (veja [`LICENSE`](LICENSE)).
|
||||
- Construído com [Actix Web](https://actix.rs), [utoipa](https://github.com/juhaku/utoipa) (Swagger UI),
|
||||
[jsonwebtoken](https://github.com/Keats/jsonwebtoken), [aes-gcm](https://github.com/RustCrypto/AEADs) e
|
||||
[sysinfo](https://github.com/GuillaumeGomez/sysinfo).
|
||||
Reference in new issue
Block a user