# 🔧 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