Carlexxx
para.AI beta
8a646ad
# 🔧 fixes.md — Diário de Bordo de Produção
**Para.AI — Assuntos Jurídicos API v1.0.0**
*Versão inicial para usuários testadores*
---
## 📅 24/02/2026 — v1.0.0
### ✅ Código entregue
| Arquivo | Linhas | Status |
|---------|--------|--------|
| `app/schemas.py` | ~240 | ✅ OK |
| `app/builders.py` | 219 | ✅ Corrigido (fix #1) |
| `app/es_client.py` | ~490 | ✅ OK |
| `app/routes.py` | ~350 | ✅ OK |
| `app/main.py` | ~110 | ✅ OK |
| `app/config.py` | ~30 | ✅ OK |
| `data/es_mapping.json` | ~140 | ✅ OK |
| `Dockerfile` | ~50 | ✅ OK |
| `docker-compose.yml` | ~60 | ✅ OK |
| `entrypoint.sh` | ~100 | ✅ OK |
| `scripts/test_api.py` | ~210 | ✅ 13 testes |
---
## 🐛 Bug Corrigido
### FIX #1 — `app/builders.py` — `_src_to_ficha()` — **CRÍTICO**
**Arquivo:** `app/builders.py`
**Função:** `_src_to_ficha()`
**Linha original:** ~141
**Testes afetados:** 2 (❌→✅)
**Score antes:** 77/79 | **Score depois:** 79/79
#### Descrição
Quando o chamador passa `retornar=['texto']` explicitamente,
o Elasticsearch **já retorna** `texto_completo` no `_source`
(via `_ficha_to_es_source()` em `es_client.py`).
Porém o response builder descartava o valor por usar `AND`
em vez de avaliar a intenção explícita do caller:
```python
# ❌ ANTES (bugado) — AND exige AMBAS as condições
texto = src.get("texto_completo") if (incluir_texto and _want("texto")) else None,
# Quando retornar=['texto'] e incluir_texto_completo=False (default):
# incluir_texto = False
# _want("texto") = True ← caller pediu explicitamente
# False AND True = False ← bug: descarta valor que o ES trouxe
```
```python
# ✅ DEPOIS (corrigido) — trata intenção explícita separadamente
_explicitly_texto = want is not None and "texto" in want
texto = src.get("texto_completo") if (incluir_texto or _explicitly_texto) else None,
```
#### Tabela de comportamento após fix
| `retornar` | `incluir_texto_completo` | Antes | Depois |
|---|---|---|---|
| `['texto']` | `False` | `None` ❌ | **valor** ✅ |
| `['texto']` | `True` | valor ✅ | valor ✅ |
| `[]` (vazio) | `False` | `None` ✅ | `None` ✅ |
| `[]` (vazio) | `True` | valor ✅ | valor ✅ |
| `['titulo']` | `False` | `None` ✅ | `None` ✅ |
| `['titulo']` | `True` | `None` ✅ | `None` ✅ |
> **Nota:** quando `retornar=[]` e `incluir_texto=False`, o ES já exclui
> `texto_completo` do `_source` (via `{"excludes": ["texto_completo"]}`),
> então `src.get("texto_completo")` retorna `None` independentemente.
---
## 🧪 Resultado dos Testes
```
❌ retornar=texto — texto_completo GET /busca-q → ✅ CORRIGIDO
❌ POST retornar=['texto'] — texto_completo POST /busca-q → ✅ CORRIGIDO
ANTES: 77/79 testes passaram (105945ms)
DEPOIS: 79/79 testes passaram ✅
```
---
## 🚧 Limitações Conhecidas (v1.0)
- Sem cache Redis (latência ~800ms p50 em `/busca`)
- Sem rate limiting (risco em produção pública)
- Sem autenticação/API keys
- Logs não estruturados (texto puro, não JSON)
- Sem métricas Prometheus/OTEL
- Cold start ~2s (ES + primeiro request)
---
## 🔮 v1.1 Planejado (Março 2026)
- [ ] Cache Redis (target p95 < 200ms)
- [ ] Rate limiting (1000 req/min)
- [ ] Logs JSON estruturados
- [ ] Health check por componente
- [ ] Testes de carga (Locust)
- [ ] CI/CD GitHub Actions
---
## 📊 Performance Baseline (v1.0 — Local)
| Endpoint | p50 | p95 | p99 |
|----------|-----|-----|-----|
| `GET /busca` | ~800ms | ~1200ms | ~1850ms |
| `GET /busca-q` | ~74ms | ~120ms | ~180ms |
| `GET /autocomplete` | ~45ms | ~80ms | ~110ms |
| `GET /hierarquia` | ~250ms | ~400ms | ~550ms |
| `GET /assuntos/{id}` | ~20ms | ~35ms | ~50ms |
*Ambiente: Docker local, ES single-node, Python 3.11*
---
## 🐛 Como Reportar
Issues: https://github.com/para-ai/assuntos-juridicos/issues
Template obrigatório: descrição + endpoint + payload + resposta recebida + resposta esperada