Skip to main content
Uma conexão é uma referência nomeada e armazenada a um banco de dados externo. Ela carrega o tipo de fonte de dados, o host e a porta, o nome do banco, as credenciais e as configurações TLS. Todo job de extração e toda chamada de esquema endereçam uma fonte de dados pelo configName da conexão, nunca pelo host dela. O Fetcher é dono da credencial desde o momento em que ela chega. Ele criptografa a senha antes do armazenamento e nunca a devolve.

O que uma conexão guarda


O Manager rejeita um modo TLS inválido para o tipo declarado. Cada driver de banco aceita um conjunto diferente de modos, e o Fetcher valida o modo contra o tipo antes de armazenar o registro.

Ciclo de vida


1

Criar

POST /v1/management/connections com o corpo da conexão e um cabeçalho X-Product-Name. O cabeçalho nomeia o produto dono da conexão. Uma criação bem-sucedida responde 201 Created.
2

Testar

POST /v1/management/connections/{id}/test abre uma conexão real com a fonte de dados e reporta a latência de ida e volta. Rode isso antes de qualquer job depender da conexão.
3

Descobrir

GET /v1/management/connections/{id}/schema retorna as tabelas e os campos que o Fetcher encontra na fonte de dados ao vivo. Veja Descoberta de esquema.
4

Usar

Referencie a conexão pelo configName dela no mapa mappedFields de um job de extração.
5

Atualizar ou excluir

PATCH aplica uma atualização parcial e deixa intocados os campos omitidos. DELETE é uma exclusão lógica: o registro guarda um carimbo de data e hora de exclusão. As duas operações respondem 409 Conflict enquanto ainda há jobs em execução contra a conexão.

Credenciais criptografadas


O Fetcher deriva quatro chaves independentes da única chave-mestra APP_ENC_KEY, por HKDF-SHA256. Uma dessas chaves protege as credenciais das fontes de dados. A senha chega ao armazenamento criptografada com AES-256-GCM, e o registro armazenado guarda a APP_ENC_KEY_VERSION que a protegeu. Essa versão é o que torna a rotação de chaves tratável: um registro declara qual chave o abre. A versão de chave vazia carrega significado. Ela marca uma fonte de dados interna — uma que um operador declara por variáveis de ambiente DATASOURCE_{NAME}_* em vez da API. O Fetcher monta essas conexões em memória na inicialização e não guarda registro algum delas em repouso. O gerenciador de segredos do próprio operador é o dono da credencial. Veja Configuração.
Os dois serviços precisam rodar com a mesma APP_ENC_KEY. O Worker precisa dela para abrir as credenciais que o Manager armazenou e para verificar a assinatura da mensagem que carregou o job. Nenhum dos serviços inicia sem uma chave válida de pelo menos 32 bytes.

Testar uma conexão


A operação de teste faz trabalho real. Ela constrói o conector, abre a fonte de dados, roda a checagem de conectividade do próprio driver e fecha o conector em todo caminho — sucesso ou falha. A resposta carrega latencyMs, a ida e volta observada em milissegundos. Use isso como sinal sobre o caminho de rede entre o Fetcher e a fonte de dados, não como um benchmark do banco de dados. O endpoint tem limite de 10 testes por minuto por conexão. Quem chama além desse orçamento recebe 429 Too Many Requests com uma dica de espera. O limite vive no Manager, não no Engine, então um hospedeiro que incorpora o Engine define a própria política. Um teste que falha diz a você que a conexão falhou. Ele não diz por quê em termos de driver. O Fetcher descarta o erro subjacente, porque esse texto pode carregar uma DSN ou uma credencial.

O 409 em jobs ativos


O Fetcher bloqueia atualização e exclusão enquanto há jobs rodando contra a conexão. PATCH /v1/management/connections/{id} e DELETE /v1/management/connections/{id} respondem 409 Conflict quando pelo menos um job ainda roda contra o configName daquela conexão.Quem chama precisa tratar isso. Trate como “ainda não”, não como “inválido”. Espere os jobs chegarem a um estado terminal e tente de novo, ou cancele-os antes.
A regra existe para manter uma extração em curso consistente com a conexão contra a qual ela foi planejada. Uma troca de host ou uma mudança de credencial no meio da extração deixaria um job lendo de uma fonte de dados que ninguém pediu. O Engine impõe essa trava por uma porta opcional, não por uma dependência dura do armazenamento de jobs. O Manager responde à pergunta a partir do repositório de jobs dele. Um hospedeiro que incorpora o Engine responde do jeito que rastreia trabalho — um conjunto em memória, um lock distribuído ou um “não” fixo. Um hospedeiro que não fornece nada não ganha trava, e as mutações seguem em frente.

Segurança de host em modo multi-tenant


Com MULTI_TENANT_ENABLED=true, o Fetcher valida o host de toda conexão fornecida por um tenant antes de discar. A validação roda em duas camadas:
  • Na análise da requisição, uma checagem sem DNS rejeita de imediato um literal de IP bloqueado.
  • Na fábrica de fontes de dados, uma checagem com resolução rejeita hostnames bloqueados como localhost e nomes de metadados de nuvem, e em seguida rejeita todo endereço para o qual o hostname resolve.
Faixas privadas, loopback e endpoints de metadados de nuvem são bloqueados. Um host rejeitado retorna 400.
Uma falha de resolução DNS deliberadamente não é um bloqueio. Transformar “não resolve” em rejeição construiria um oráculo de reconhecimento e faria conexões legítimas falharem durante um problema transitório de DNS. O driver expõe o próprio erro de conexão no lugar.
A proteção nunca se aplica a fontes de dados internas. Um operador que configura uma fonte de dados por variáveis de ambiente já tomou essa decisão.

Operações de migração


Duas operações existem apenas para conexões anteriores ao escopo por produto:
  • GET /v1/management/connections/unassigned lista conexões sem produto.
  • POST /v1/management/connections/{id}/assign vincula uma ao produto do cabeçalho X-Product-Name.
A atribuição é única e irreversível. Uma segunda tentativa em uma conexão já atribuída retorna um conflito.

Próximos passos


Descoberta de esquema

Leia o esquema de uma fonte de dados, mantenha-o em cache e valide um job contra ele.

Arquitetura

O Manager, o Worker e o Engine sobre o qual os dois rodam.