Uma chave-mestra, quatro chaves derivadas
APP_ENC_KEY é a única chave que você fornece. Gere-a com make generate-master-key, que produz um valor de 32 bytes codificado em base64. Defina o mesmo valor no Manager e no Worker.
O Fetcher nunca usa essa chave diretamente. Ele a expande com HKDF-SHA256 (RFC 5869) em quatro chaves independentes, uma por finalidade.
A separação é o ponto. Um consumidor que tem a chave externa consegue conferir a assinatura de um resultado. Ele não consegue descriptografar uma credencial armazenada, e não consegue forjar uma mensagem entre os dois serviços.
Versão de chave e rotação
APP_ENC_KEY_VERSION rotula a chave em vigor. Todo registro de conexão guarda a versão que criptografou a senha dele, então o operador sabe a qual chave um registro pertence. Incremente a versão quando trocar a chave-mestra.
Duas consequências acompanham uma troca de chave-mestra:
- Credenciais armazenadas. Uma conexão criptografada sob a chave anterior pertence à chave anterior. Registre essas conexões de novo sob a nova chave.
- Verificação externa. A chave HMAC externa muda junto com a chave-mestra. Derive a nova chave e entregue-a a todo consumidor que confere assinaturas. Resultados anteriores verificam contra a chave anterior.
make derive-key KEY="<sua-chave-mestra-base64>". A ferramenta também lê APP_ENC_KEY do ambiente, ou a chave da entrada padrão, e imprime uma chave hexadecimal de 64 caracteres.
Credenciais em repouso
Uma senha de fonte de dados nunca chega ao MongoDB em texto claro. O Manager a criptografa com AES-256-GCM sob a chave de credencial derivada, e então armazena o texto cifrado e a versão da chave. Fontes de dados internas declaradas por
DATASOURCE_{NAME}_* são a exceção deliberada. Elas vêm do ambiente do próprio operador, e o Fetcher as marca como internas com uma versão de chave vazia.
Resultados em repouso
O Worker protege um resultado armazenado em dois passos:
- Ele assina o JSON em texto claro com HMAC-SHA256 sob a chave externa derivada, e registra o algoritmo e a assinatura junto com o resultado.
- Ele criptografa o payload com AES-GCM sob a chave de armazenamento derivada, com um nonce aleatório novo de 12 bytes, e armazena o resultado codificado em base64.
scripts/crypto/derive-key/verification-guide.md.
O modo direct devolve as linhas inline, sem criptografia. O Engine as reporta como texto claro e anexa um digest SHA-256 sobre os bytes exatos.
Mensagens assinadas entre os serviços
Toda mensagem RabbitMQ que o Manager publica para o Worker carrega uma assinatura HMAC-SHA256 sob a chave interna derivada. A assinatura cobre mais do que o corpo. Ela amarra:
- o timestamp e a versão da assinatura,
- o identificador do tenant,
- o identificador do job,
- o exchange e a routing key,
- o corpo da mensagem.
Validação de host da fonte de dados
Um tenant que registra a própria conexão poderia apontá-la para a sua rede interna. Com
MULTI_TENANT_ENABLED=true, o Fetcher checa o host antes de conectar.
A validação roda em duas camadas:
- Na leitura da requisição. O Fetcher rejeita um literal de IP em uma faixa bloqueada, sem consulta de DNS.
- Na fábrica de fontes de dados. O Fetcher checa o hostname contra uma blocklist que cobre
localhost, nomes de metadados de nuvem e os sufixos.local,.internale.cluster.local. Ele então resolve o hostname e checa todos os endereços que recebe de volta.
lib-commons, então todo produto Lerian compartilha uma lista só.
Fontes de dados internas configuradas pelo operador são isentas por construção. Elas vêm do seu ambiente, e não de uma requisição de tenant.
Isolamento de tenant
O Engine coloca toda operação sob o escopo do identificador de tenant, e esse identificador é a única fronteira de isolamento que ele tem. Um identificador de tenant malformado falha antes de o Fetcher tocar qualquer recurso. Em modo multi-tenant, cada tenant recebe o próprio banco de metadados, resolvido a partir das claims do JWT na requisição pelo middleware de tenant. O acesso falha de forma fechada. Uma requisição que carrega uma identidade de tenant sem banco de tenant resolvido retorna um erro em vez de ler o banco compartilhado.
Autenticação e superfícies de sonda
PLUGIN_AUTH_ENABLED=true coloca o middleware do Access Manager na frente da API. As requisições passam a carregar um bearer token, e o Fetcher autoriza cada operação contra um recurso e uma ação.
/health, /readyz, /readyz/tenant/:id, /metrics e /version montam antes desse middleware, então as sondas do Kubernetes e do balanceador de carga seguem sem autenticação.
Erros nunca vazam material de conexão
O Fetcher descarta o erro bruto do driver na fronteira do Engine e devolve uma mensagem fixa no lugar. Um erro bruto de driver pode embutir uma DSN ou uma credencial, então quem chama vê
failed to connect to datasource em vez da string que o driver produziu.
As falhas chegam classificadas em categorias estáveis — validação, não autorizado, proibido, limite excedido, conexão, tempo limite e outras — então um hospedeiro as mapeia para os próprios códigos de status sem interpretar texto.
Próximos passos
Configuração
Cada variável de ambiente, por componente.
Implantação
Dependências, retenção no armazenamento, escala e checagens de inicialização.
Observabilidade
Sondas, comportamento de drenagem, métricas e tracing.
Conexões
Registre, teste e use uma conexão.

