# documents Serviço de documentos e licenças dos postos: catálogo legal (parametrizável por UF), documentos com trilha de versões, resumo de conformidade, análise de upload e régua de alertas de vencimento. É o backend do menu **Documentos** do painel (`clubpetro-frontend`, `REACT_APP_DOCUMENTS_API=true`). Espelho do serviço [`routines`](../routines) — NestJS 10 + Fastify + TypeORM/PostgreSQL, exceções mapeadas com prefixo `DOC`, upload em bucket GCS privado com URL assinada. ## Endpoints | Método | Rota | O que faz | |---|---|---| | GET | `/catalog?uf=SP` | Catálogo legal com variação estadual aplicada | | GET | `/documents?programId&storeId` | Documentos da loja (status derivado na leitura) | | POST | `/documents` (multipart) | Cria obrigação ou registra renovação (versão nova, trilha preservada) | | POST | `/documents/analyze` (multipart) | Sugere tipo/datas do arquivo (v1: keywords; v1.1: OCR/LLM) | | POST | `/documents/:id/protocol` | Registra o protocolo de renovação no órgão (status → em renovação) | | PATCH | `/documents/:id/details` | Responsável e observações | | GET | `/compliance/summary?programId&storeId` | Score 0–100 ponderado por criticidade + totais | | GET | `/compliance/upcoming?days=90` | Vencimentos na janela, ordenados | | GET | `/alerts/preview` | O que a régua (lead/30/15/7/1/vencido) enviaria hoje | | GET | `/health` | Probe do Kubernetes | Regras de negócio centrais em `src/modules/common/utils/status.util.ts` (status) e `src/modules/compliance/compliance.service.ts` (score) — as mesmas do painel, agora com o backend como fonte da verdade. O detalhe jurídico que o modelo carrega: **renovação protocolada no prazo mantém o documento operante** (na LO da CETESB, protocolo ≥120 dias antes prorroga a validade). ## Análise por LLM Com `ANTHROPIC_API_KEY` no ambiente, o `POST /documents/analyze` extrai os campos do PDF/imagem com um modelo multimodal (`DOCUMENTS_LLM_MODEL`, default Haiku): confiança por campo (`fieldConfidences`), citação do trecho de origem (`evidence`) e **dupla passada em datas** — divergência entre as duas leituras zera o campo e devolve o warning `dateMismatch`, porque data errada é pior que campo vazio. Qualquer falha do LLM (API fora, arquivo >10MB, mime estranho) cai na heurística por nome de arquivo com o warning `llmUnavailable` — a análise nunca quebra o upload. Sem a chave, o serviço se comporta como o v1 (heurística pura). ## Rodar local ```bash cp .env.example .env # preencher SECRET_TOKEN yarn && yarn start:dev # migrations rodam no boot (TYPEORM_MIGRATIONS_RUN=true) yarn test # 38 testes, cobertura mínima 65/73/73/73 ``` ## Deploy (lab) `k8s/hml/` uma vez à mão; depois `branch → PR → merge → cd.yml` (Cloud Build). Pré-requisitos novos no ambiente: database `documents` na instância `clubpetro-homologation` e bucket privado `corepetro_store_documents`.