# Voyager (central) + Agentes (opcionais) Este ZIP adiciona uma arquitetura **distribuída e opcional** para o Voyager: - **Central (ScrapperAPI)** continua capaz de fazer o scrape localmente. - **Agentes (VoyagerAgent)** são *opcionais*: quando habilitados, eles pegam lotes de URLs do central via **gRPC** e devolvem o conteúdo. - A coordenação é feita por **lease** no banco (PostgreSQL). Se um agente morrer, o lease expira e outro worker pode recuperar o item. ## Visão geral - Banco: a tabela `queue` ganhou colunas `leased_by` e `lease_expires_at`, além de `attempts` e `last_error`. - Central expõe um gRPC `AgentService` para: - `RegisterAgent` (registro + thumbprint do cert) - `Heartbeat` - `LeaseWork` (lote de URLs) - `SubmitResult` (conteúdo + status) - Segurança: recomendado **mTLS** (TLS mútuo) no endpoint gRPC. ## Modos (Workers.Mode) Em `ScrapperAPI/appsettings*.json`: - `LocalOnly`: **somente** worker local. - `Hybrid` (padrão): local + agentes ao mesmo tempo. - `PreferAgents`: local só trabalha quando não há agentes ativos (por uma janela de graça). - `PreferLocal`: (reservado) mantenha local sempre ativo. ## Como rodar (dev) 1) Rode o banco e aplique o script: - `ScrapperAPI/Scripts/database.sql` 2) Rode o central: - `dotnet run --project ScrapperAPI` 3) (Opcional) Rode um agente: - ajuste `VoyagerAgent/appsettings.json` com `CentralGrpcAddress` e `SessionIds` - `dotnet run --project VoyagerAgent` > Em dev, você pode deixar `Workers:Agents:RequireMutualTls=false` para testar sem cert. ## Como habilitar mTLS (produção) ### 1) Gere uma CA local e certs (exemplo) > Ajuste paths conforme seu ambiente. ```bash # CA openssl genrsa -out ca.key 4096 openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -subj "/CN=Voyager-CA" -out ca.crt # Servidor (central) openssl genrsa -out server.key 2048 openssl req -new -key server.key -subj "/CN=voyager-grpc" -out server.csr openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 825 -sha256 # Agente openssl genrsa -out agent01.key 2048 openssl req -new -key agent01.key -subj "/CN=agent-01" -out agent01.csr openssl x509 -req -in agent01.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out agent01.crt -days 825 -sha256 # PFX do agente openssl pkcs12 -export -out agent-01.pfx -inkey agent01.key -in agent01.crt -certfile ca.crt ``` ### 2) Configure o Kestrel do central A forma mais comum é via `appsettings.Production.json` (exemplo): ```json { "Kestrel": { "Endpoints": { "HttpsGrpc": { "Url": "https://0.0.0.0:7443", "Certificate": { "Path": "./certs/server.pfx", "Password": "change-me" } } } }, "Workers": { "Agents": { "Enabled": true, "RequireMutualTls": true } } } ``` > Observação: o código do gRPC **exige cert do cliente** quando `RequireMutualTls=true`. ### 3) Configure o agente Em `VoyagerAgent/appsettings.json`: - `ClientCertificatePath` -> `./certs/agent-01.pfx` - `ClientCertificatePassword` -> senha do PFX - `CentralGrpcAddress` -> https do central (porta 7443, por exemplo) ### 4) Registro do agente Ao iniciar, o agente chama `RegisterAgent` e o central grava: - `agent.id` - `agent.cert_thumbprint` Depois disso, os requests são validados pelo thumbprint. ## O que foi adicionado/alterado - `queue`: lease + tentativas - `agent`: tabela para registrar agentes (thumbprint) - `IQueueRepository`: lease batch, renew, mark done/failed validando `leased_by` - `ScrapperAPI`: gRPC `AgentServiceImpl` - `VoyagerAgent`: Worker Service que faz lease + scrape + submit