{"id":50386424,"url":"https://github.com/opastorello/cpf-validador","last_synced_at":"2026-05-30T15:01:00.914Z","repository":{"id":353243045,"uuid":"1185897484","full_name":"opastorello/cpf-validador","owner":"opastorello","description":"🔍 Valide CPFs e descubra a quem pertencem — MCP tools + REST API + interface web com CAPTCHA solver via CRNN","archived":false,"fork":false,"pushed_at":"2026-04-23T04:04:15.000Z","size":81,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-23T04:24:36.895Z","etag":null,"topics":["captcha","cpf","crnn","fastapi","fastmcp","mcp","ocr","python","pytorch","trabalhista","trt3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opastorello.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-19T03:42:17.000Z","updated_at":"2026-04-23T04:04:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/opastorello/cpf-validador","commit_stats":null,"previous_names":["opastorello/cpf-validador"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/opastorello/cpf-validador","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opastorello%2Fcpf-validador","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opastorello%2Fcpf-validador/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opastorello%2Fcpf-validador/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opastorello%2Fcpf-validador/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opastorello","download_url":"https://codeload.github.com/opastorello/cpf-validador/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opastorello%2Fcpf-validador/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33696683,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["captcha","cpf","crnn","fastapi","fastmcp","mcp","ocr","python","pytorch","trabalhista","trt3"],"created_at":"2026-05-30T15:01:00.036Z","updated_at":"2026-05-30T15:01:00.833Z","avatar_url":"https://github.com/opastorello.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🔍 CPF Validador\n\n\u003e Valide CPFs, descubra a quem pertencem e encontre o CPF correto a partir de dígitos parciais ou ilegíveis — com resolução automática de CAPTCHA via rede neural treinada localmente.\n\nExpõe as mesmas operações como **MCP tools** (para agentes AI) e **REST API** (para integrações diretas), com interface web incluída.\n\n---\n\n## 💡 O que este projeto faz\n\n| | |\n|--|--|\n| ✅ | Valida se um CPF é matematicamente correto |\n| 👤 | Confirma a quem um CPF pertence pelo nome |\n| 🔎 | Descobre o CPF completo a partir de dígitos parciais ou ilegíveis |\n| 👥 | Processa dezenas de CPFs em paralelo |\n| 🤖 | Integra com qualquer agente AI via protocolo MCP |\n\nPara confirmar a titularidade de um CPF, o sistema consulta o **TRT3** — que emite certidões públicas associando CPF e nome. A resolução de CAPTCHA é feita por uma **CRNN (Convolutional Recurrent Neural Network)** treinada especificamente para isso, atingindo **~99% de acurácia** sem depender de nenhum serviço externo.\n\n---\n\n## 🤖 MCP Tools\n\n| Tool | Descrição |\n| ---- | --------- |\n| `validate_cpf` | Valida matematicamente um CPF pelo algoritmo módulo-11 |\n| `generate_valid_variations` | Gera todas as variações válidas de um CPF com dígitos errados ou ilegíveis |\n| `check_feitos_trabalhistas` | Confirma titularidade de um CPF consultando o TRT3 |\n| `find_cpf_by_mask` | Descobre o CPF completo a partir de uma máscara com `*` nos dígitos desconhecidos |\n| `find_cpf_by_variations` | Dado um CPF parcial ou errado, encontra o correto filtrando pelo nome |\n| `check_multiple_cpfs` | Valida e confirma titularidade de uma lista de CPFs em paralelo |\n\n---\n\n## 🌐 REST API\n\n| Método | Rota | Rate limit | Descrição |\n| ------ | ---- | ---------- | --------- |\n| `GET`  | `/` | — | Interface web |\n| `POST` | `/cpf/validate` | — | Valida um CPF matematicamente |\n| `POST` | `/cpf/variations` | — | Gera variações válidas de um CPF |\n| `POST` | `/trt3/feitos` | 10/min por IP | Confirma titularidade de um CPF via TRT3 |\n| `POST` | `/trt3/feitos-multiplos` | 5/min por IP | Confirma lista de CPFs em paralelo |\n| `POST` | `/trt3/buscar-por-mascara` | 3/min por IP | Descobre CPF por máscara com `*` |\n| `POST` | `/trt3/buscar-por-variacoes` | 3/min por IP | Descobre CPF correto a partir de variações |\n| `GET`  | `/history/` | — | Lista o histórico de consultas realizadas |\n| `POST` | `/history/save` | — | Salva ou atualiza uma entrada no histórico |\n| `DELETE` | `/history/` | — | Limpa todo o histórico |\n| `DELETE` | `/history/{cpf}` | — | Remove a entrada de um CPF específico |\n| `GET`  | `/health` | — | Health check — retorna `{\"status\": \"ok\"}` |\n\nDocumentação interativa: `http://localhost:8000/docs` (disponível apenas em `ENV=development`).\n\n### 📂 Histórico de consultas\n\nO histórico é **global e compartilhado** — todas as consultas feitas pela interface web, pela REST API ou via MCP gravam no mesmo arquivo de histórico do servidor.\n\n- **Interface web:** o usuário pode ativar ou desativar o salvamento automático individualmente, através do toggle na aba Histórico. A preferência é salva no `localStorage` do navegador e não afeta outras interfaces.\n- **REST API / MCP:** toda consulta bem-sucedida é registrada no histórico global, independente do token utilizado.\n\n\u003e **Roadmap:** no futuro está prevista a opção de múltiplos históricos isolados por token — permitindo que cada integração (web, API, MCP) mantenha seu próprio registro separado.\n\n---\n\n## 🏗️ Arquitetura\n\nFastAPI com FastMCP 3.0 montado em `/mcp` (streamable-http). A camada `services/` não tem dependência de framework — a mesma lógica é consumida pelos routers REST e pelo MCP server.\n\n```\napp/\n├── main.py             # FastAPI — routers + mcp.http_app() em /mcp + rate limiter\n├── config.py           # Lê todas as variáveis de ambiente com defaults\n├── mcp_server.py       # FastMCP(\"cpf-validador\") — 6 tools\n├── auth.py             # TokenMiddleware — autenticação via API_TOKEN + controle prod/dev\n├── services/\n│   ├── cpf.py          # Validação, variações e geração por máscara (zero deps de framework)\n│   └── trt3.py         # Consulta TRT3: curl_cffi + CAPTCHA solver + pypdf\n├── routers/\n│   ├── cpf.py          # POST /cpf/validate, POST /cpf/variations\n│   ├── trt3.py         # POST /trt3/feitos, /feitos-multiplos, /buscar-por-mascara, /buscar-por-variacoes\n│   ├── history.py      # GET/POST/DELETE /history/ — histórico de consultas\n│   └── ui.py           # GET / — interface web\n└── captcha/\n    ├── model.py        # Arquitetura CRNN (CNN + BiLSTM + CTC Loss)\n    ├── predictor.py    # Inferência: carrega captcha_model.pt e prediz\n    ├── dataset.py      # CaptchaDataset com data augmentation\n    ├── train.py        # Loop de treino com early stopping + AMP + registry\n    ├── collector.py    # Coleta amostras rotuladas direto do TRT3\n    ├── registry.py     # Versionamento de modelos (models/vN/model.pt + meta.json)\n    └── models/         # Histórico de versões treinadas\n```\n\n**Regras de camada:**\n- `services/` — zero imports de FastAPI ou FastMCP\n- `routers/` e `mcp_server.py` — importam apenas de `services/`\n- I/O bloqueante em `services/trt3.py` é sempre executado via `run_in_threadpool`\n\n---\n\n## ⚙️ Configuração\n\nTodas as opções são lidas de variáveis de ambiente ou do arquivo `.env` na raiz do projeto.\n\n### Referência completa de variáveis\n\n| Variável | Padrão | Descrição |\n| -------- | ------ | --------- |\n| `API_TOKEN` | *(vazio — sem auth)* | Token Bearer. Se vazio, todos os endpoints ficam abertos |\n| `ENV` | `development` | `development` ou `production` — controla quais rotas ficam abertas sem token |\n| `TRT3_BASE_URL` | `https://certidao.trt3.jus.br` | URL base do site do TRT3 |\n| `TRT3_FORM_PATH` | `/certidao/feitosTrabalhistas/aba1.emissao.htm` | Path do formulário de consulta |\n| `HTTP_TIMEOUT` | `30` | Timeout (segundos) para requisições HTTP ao TRT3 |\n| `CAPTCHA_TIMEOUT` | `15` | Timeout (segundos) para download da imagem CAPTCHA |\n| `MAX_CAPTCHA_ATTEMPTS` | `20` | Tentativas máximas de resolver o CAPTCHA antes de desistir |\n| `RETRY_DELAY` | `1.0` | Segundos de espera entre tentativas de CAPTCHA |\n| `DEFAULT_WORKERS` | `8` | Threads paralelas padrão nas consultas em lote |\n| `MAX_WORKERS` | `20` | Limite máximo de `workers` que o cliente pode solicitar |\n| `TASK_TIMEOUT` | `60` | Timeout (segundos) por CPF individual em consultas paralelas |\n| `MAX_WILDCARDS_IN_MASK` | `5` | Máximo de `*` na parte base da máscara (evita explosão combinatória) |\n| `RATE_LIMIT_FEITOS` | `10/minute` | Rate limit de `/trt3/feitos` por IP |\n| `RATE_LIMIT_MULTIPLOS` | `5/minute` | Rate limit de `/trt3/feitos-multiplos` por IP |\n| `RATE_LIMIT_MASK` | `3/minute` | Rate limit de `/trt3/buscar-por-mascara` por IP |\n| `RATE_LIMIT_VARIACOES` | `3/minute` | Rate limit de `/trt3/buscar-por-variacoes` por IP |\n| `CAPTCHA_MODEL_PATH` | *(vazio — usa `app/captcha/captcha_model.pt`)* | Path absoluto para o modelo `.pt` (útil para montar modelo externo) |\n| `HISTORY_RETENTION_DAYS` | `90` | Dias de retenção do histórico (LGPD). `0` = sem limite |\n| `APP_TIMEZONE` | `America/Sao_Paulo` | Timezone para timestamps do histórico |\n\n### 🔒 Rotas abertas por ambiente\n\n| Rota | `development` | `production` |\n| ---- | :-----------: | :----------: |\n| `/` | ✅ aberta | ✅ aberta |\n| `/health` | ✅ aberta | ✅ aberta |\n| `/docs` | ✅ aberta | 🔒 token |\n| `/redoc` | ✅ aberta | 🔒 token |\n| `/openapi.json` | ✅ aberta | 🔒 token |\n| `/mcp` | 🔒 token | 🔒 token |\n| demais | 🔒 token | 🔒 token |\n\n\u003e Se `API_TOKEN` estiver vazio, o middleware ignora autenticação em qualquer ambiente.\n\n---\n\n## 🔐 Autenticação\n\nCom `API_TOKEN` configurado, todas as requisições protegidas precisam enviar:\n\n```\nAuthorization: Bearer meu-token-secreto\n```\n\n**REST:**\n\n```bash\ncurl -X POST http://localhost:8000/trt3/feitos \\\n  -H \"Authorization: Bearer meu-token-secreto\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"cpf\": \"529.982.247-25\"}'\n```\n\n**Claude Desktop / Claude Code (`claude_desktop_config.json`):**\n\n```json\n{\n  \"mcpServers\": {\n    \"cpf-validador\": {\n      \"command\": \"npx\",\n      \"args\": [\"mcp-remote\", \"http://localhost:8000/mcp\", \"--allow-http\"],\n      \"env\": {\n        \"MCP_REMOTE_HEADER_AUTHORIZATION\": \"Bearer meu-token-secreto\"\n      }\n    }\n  }\n}\n```\n\nA interface web (`/`) exibe um **gate de autenticação** quando `API_TOKEN` está definido — o token é validado contra o servidor e salvo no navegador.\n\n---\n\n## 🚀 Instalação\n\n### Docker (recomendado)\n\n```bash\ngit clone https://github.com/opastorello/cpf-validador.git\ncd cpf-validador\ncp .env.example .env   # edite se quiser definir API_TOKEN\ndocker compose up --build -d\n```\n\n### Local\n\n```bash\npip install -r requirements.txt\ncp .env.example .env\nuvicorn app.main:app --host 0.0.0.0 --port 8000 --reload\n```\n\nApós iniciar:\n- Interface web: `http://localhost:8000/`\n- REST docs: `http://localhost:8000/docs` *(apenas em `ENV=development`)*\n- MCP endpoint: `http://localhost:8000/mcp`\n\n---\n\n## 📋 Exemplos de uso\n\n### Validar um CPF\n\n```bash\ncurl -X POST http://localhost:8000/cpf/validate \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"cpf\": \"529.982.247-25\"}'\n```\n\n### Confirmar titularidade\n\n```bash\ncurl -X POST http://localhost:8000/trt3/feitos \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"cpf\": \"529.982.247-25\"}'\n```\n\n```json\n{\n  \"cpf\": \"529.982.247-25\",\n  \"encontrado\": true,\n  \"nome_certidao\": \"JOAO DA SILVA\",\n  \"valida_ate\": \"18/04/2026\",\n  \"numero_certidao\": \"2026/123456\"\n}\n```\n\n### Descobrir CPF por máscara\n\nQuando você conhece apenas parte dos dígitos — substitua os desconhecidos por `*`:\n\n```bash\ncurl -X POST http://localhost:8000/trt3/buscar-por-mascara \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"mascara\": \"***.123.456-**\", \"nome\": \"João Silva\"}'\n```\n\nO servidor gera todas as combinações válidas para as posições com `*`, consulta em paralelo e retorna apenas os matches com o nome informado.\n\n\u003e Máximo de 5 wildcards na parte base (posições 0–8) = até 100.000 combinações. Configurável via `MAX_WILDCARDS_IN_MASK`.\n\n### Recuperar CPF com erros ou dígito faltando\n\n```bash\ncurl -X POST http://localhost:8000/trt3/buscar-por-variacoes \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"cpf_parcial\": \"5299824725\", \"nome\": \"joao\"}'\n```\n\n### Consulta em lote\n\n```bash\ncurl -X POST http://localhost:8000/trt3/feitos-multiplos \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"cpfs\": [\"529.982.247-25\", \"111.444.777-35\"], \"workers\": 4}'\n```\n\n---\n\n## 🧠 Modelo de CAPTCHA\n\n### Arquitetura CRNN\n\n```\nInput (1×60×160)\n    → Conv2D ×4 + BatchNorm + ReLU + MaxPool   (extração de features visuais)\n    → BiLSTM ×2 (128 hidden, bidirectional)    (modelagem de sequência)\n    → Linear → CTC Loss                         (decode sem segmentação)\nOutput: string de 5 caracteres [0-9a-z]\n```\n\n### Bootstrapping em 3 rodadas\n\n| Rodada | Amostras | Rotulador | Acurácia dos labels | Acurácia do modelo |\n| ------ | -------- | --------- | :-----------------: | :----------------: |\n| 1 | 15.000 | ddddocr (OCR genérico) | ~43% | **98.70%** |\n| 2 | 20.000 | Modelo R1 | ~96% | **98.80%** |\n| 3 | 20.000 | Modelo R2 | ~99.3% | **98.55%** |\n\n**Total: 55.000 amostras.** O modelo final (v1) convergiu na época 106/120 com `val_loss=0.0072`.\n\n### Hiperparâmetros\n\n- **Optimizer:** AdamW | **LR:** 1e-3 com CosineAnnealingLR\n- **Epochs:** 120 com early stopping (patience: 20)\n- **Batch size:** 128 | **Treino:** GPU com AMP float16 via `torch.amp.autocast`\n- **Inferência:** CPU-only (Docker)\n- **Augmentation:** rotação, shear, translate, color jitter, gaussian blur, random erasing\n\n---\n\n## Treinar o modelo\n\n**1. Coletar amostras**\n\n```bash\npython -m app.captcha.collector --cpf 000.000.000-00 --target 15000 --workers 4\n```\n\n**2. Treinar**\n\n```bash\npython -m app.captcha.train --epochs 120 --batch 128 --lr 1e-3\n```\n\nO melhor modelo (menor `val_loss`) é salvo em `app/captcha/captcha_model.pt`.\n\n**3. Bootstrap (melhora qualidade dos labels)**\n\n```bash\nrm -rf app/captcha/data/\npython -m app.captcha.collector --cpf 000.000.000-00 --target 20000 --workers 4\npython -m app.captcha.train --epochs 120 --batch 128 --lr 1e-3\n```\n\nRepita 2–3 rodadas até a acurácia estabilizar. Para consultar o histórico de versões:\n\n```bash\npython -m app.captcha.registry\n```\n\n---\n\n## 📦 Dependências principais\n\n| Pacote | Uso |\n| ------ | --- |\n| [FastMCP](https://github.com/jlowin/fastmcp) | Framework MCP server |\n| [FastAPI](https://github.com/fastapi/fastapi) | REST API |\n| [slowapi](https://github.com/laurentS/slowapi) | Rate limiting por IP |\n| [curl-cffi](https://github.com/yifeikong/curl-cffi) | HTTP com impersonação TLS Chrome-124 |\n| [PyTorch](https://github.com/pytorch/pytorch) | Rede neural CRNN para CAPTCHA |\n| [torchvision](https://github.com/pytorch/vision) | Transforms e augmentation de imagem |\n| [pypdf](https://github.com/py-pdf/pypdf) | Extração de dados do PDF de certidão |\n| [Pillow](https://github.com/python-pillow/Pillow) | Processamento de imagem |\n| [python-dotenv](https://github.com/theskumar/python-dotenv) | Carregamento de variáveis do `.env` |\n\n---\n\n## 🗺️ Roadmap\n\nIdeias e melhorias planejadas para versões futuras.\n\n### Escalabilidade\n- **Worker distribuído** — arquitetura de fila (Redis + worker nodes) onde cada nó é uma VPS com IP próprio contribuindo com slots de conexão ao TRT3. Escala horizontalmente: 1 worker = 20 slots, 5 workers = 100 slots, IPs diferentes reduzem risco de throttling.\n- **Cache de resultados** — CPFs já consultados recentemente retornam resultado armazenado sem nova requisição ao TRT3. Reduz latência e carga no tribunal.\n\n### Multi-usuário\n- **Histórico isolado por token** — cada integração (web, API, MCP) mantém seu próprio registro separado em vez do histórico global compartilhado atual.\n- **Quota de consultas por token** — cada token teria um limite mensal/diário de consultas configurável independentemente do rate limit por IP. Ex: token A = 1.000 consultas/dia, token B = 10.000/dia.\n- **Workers por token** — cada token teria um número máximo de workers simultâneos ao TRT3. Ex: token gratuito = 2 workers, token premium = 20 workers. Garante que um único cliente não monopoliza a capacidade do servidor enquanto outros aguardam.\n\n### Cobertura\n- **Suporte a outros tribunais** — expandir para TRT1 (RJ), TRT2 (SP) e demais regiões, consolidando resultados em uma única consulta.\n- **Consulta à Receita Federal** — validar situação cadastral do CPF diretamente na base da RF.\n\n### Observabilidade\n- **Dashboard de uso** — visualizar volume de consultas, taxa de acerto do CAPTCHA e latência média por endpoint.\n- **Alerta de bloqueio** — detectar automaticamente quando o TRT3 começa a retornar erros acima do normal e notificar.\n\n---\n\n## ⚖️ Responsabilidade de Uso\n\nEste projeto consulta exclusivamente o sistema público do **TRT3** ([certidao.trt3.jus.br](https://certidao.trt3.jus.br)) — os mesmos dados acessíveis por qualquer pessoa pelo navegador, sem login ou cadastro. As certidões emitidas são documentos públicos por determinação legal.\n\n**Usos adequados:**\n- Due diligence em processos de contratação\n- Verificação de titularidade em contextos jurídicos ou de compliance\n- Integração com agentes AI para automação de processos legítimos\n\n**O projeto não se destina a:**\n- Varredura em massa sem finalidade específica\n- Coleta de dados para fins não autorizados pela LGPD\n- Qualquer uso que viole a legislação brasileira vigente\n\nO código é aberto e auditável. A responsabilidade pelo uso é inteiramente do operador que implanta e utiliza o serviço. Rate limiting está configurado por padrão para desincentivar abuso.\n\n---\n\n## 📄 Licença\n\n[MIT](LICENSE) © 2026 Nícolas Pastorello\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopastorello%2Fcpf-validador","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopastorello%2Fcpf-validador","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopastorello%2Fcpf-validador/lists"}