O cliente open-source de aplicação para bases de dados de schema. Execute-o em qualquer máquina que consiga aceder ao seu próprio PostgreSQL, emparelhe uma vez e ele mantém essa base de dados convergente com os seus enriquecimentos — arrancando a partir de um snapshot e depois aplicando um fluxo de deltas em tempo real através de um único WebSocket de saída. A sua string de ligação nunca sai dessa máquina.
Cada instrução é protegida por revisão, pelo que um batch reentregue converge para as mesmas linhas. Um erro de SQL faz rollback ao batch e interrompe-o — um delta problemático nunca é ignorado silenciosamente.
O cliente obtém estado, não operações: cada delta transporta a(s) linha(s) atual(is) completa(s) de uma entity alterada como um INSERT … ON CONFLICT … DO UPDATE idempotente, para que o destino convirja mesmo que um batch tenha sido perdido.
Os database syncs podem ser consumidos de várias formas — n8n, Make.com, MCP, webhooks diretos ou o feed delta REST. O cliente de sincronização é o caminho totalmente automatizado: o que menos exige construir e o que menos expõe.
Sem scenario do n8n, sem cron, sem código de ligação. Emparelhe uma vez e ele arranca a partir do snapshot, aplicando depois cada delta à medida que chega.
A connection string é passada na linha de comandos ou armazenada localmente em modo 600 — nunca é enviada para o Entity Enricher. O cliente liga-se apenas para o exterior.
Cada delta é um upsert idempotente e protegido por revisão. Se o cliente falhar a meio de um batch, o batch é reentregue após a expiração da sua concessão e a reaplicação converge para as mesmas linhas.
Um erro de SQL reverte o lote e reporta o delta que falhou. O servidor coloca todo o lote desse enriquecimento em quarentena e reenvia a fila sem ele, pelo que o cliente permanece ligado e continua a aplicar — uma linha problemática não pode bloquear tudo o que vem atrás, e o trabalho em quarentena continua listado até que trate dele.
Registe primeiro uma base de dados num schema, depois emparelhe um cliente e execute-o numa máquina que consiga aceder à sua base de dados.
Na página Database Sync, registe uma base de dados no esquema que pretende espelhar e reveja as respetivas chaves de base de dados. Consulte Database Sync para conhecer o modelo completo. Este passo declara o dialeto de destino que o cliente irá aplicar.
Cole isto num terminal. O script verifica uma assinatura cosign antes de instalar.
curl -fsSL https://entityenricher.ai/install-eedatabase.sh | sh
Windows: iwr -useb https://entityenricher.ai/install-eedatabase.ps1 | iex. Ou transfira um binário assinado a partir das Versões, ou compile a partir do código-fonte (Go ≥ 1.23): go build -o ee-database .
O código-fonte e as versões assinadas encontram-se em TOT-Concept/ee-database (MIT).
Execute ee-database pair. Abre-se um separador do navegador em /database/connect com um código curto — confirme-o e escolha que base de dados este cliente deve sincronizar.
ee-database pair --server https://entityenricher.ai Open this URL in your browser to confirm pairing: https://entityenricher.ai/database/connect?code=7QX-KP2 Code: 7QX-KP2 Waiting for confirmation...
Prefere um token? Emita um na página Database Sync (Cliente de sincronização → Emparelhar um cliente) e passe-o diretamente: ee-database pair --server … <refresh-token>.
Na primeira execução, o cliente obtém o snapshot .sql e aplica-o, ligando-se depois e transmitindo deltas. --save-dsn guarda a string de ligação localmente, para que as execuções seguintes não precisem de argumentos.
Cada execução também verifica automaticamente os direitos de aprovisionamento do login (criar base de dados, DDL, DML) e reporta o resultado no cartão do cliente de sincronização, pelo que uma permissão em falta fica visível antes de os deltas falharem ao aplicar. Se ainda não houver nenhum esquema associado publicado, o cliente permanece ligado e aguarda — a primeira publicação inicia o fluxo por si só, sem necessidade de reiniciar.
ee-database run --dsn "postgres://user:pass@localhost:5432/mydb" --save-dsn
“Ao lado” significa adjacente na rede, não no servidor da base de dados: qualquer máquina ou contentor que consiga alcançar a DSN funciona — incluindo PostgreSQL gerido na cloud (Azure, OVHcloud, AWS RDS…), que normalmente impõe TLS: …/mydb?sslmode=require.
Várias bases de dados na mesma máquina? Um host de sincronização sobe a cerimónia de emparelhamento um nível: emparelhe a máquina uma vez e cada sincronização de base de dados que lhe atribuir é reclamada, aprovisionada e mantida sincronizada automaticamente — registar uma nova sincronização nunca exige outra sessão de terminal. Requer o cliente 1.5.0 ou posterior, que emparelha uma vez por servidor em vez de uma vez por máquina — assim, um único host pode servir várias instâncias de Entity Enricher lado a lado.
Na página Database Sync, clique no botão Sync hosts da barra de ferramentas e adicione um host com o nome da máquina. É apresentado uma única vez um token de emparelhamento descartável, incorporado num comando host pair pronto a copiar, com passos de configuração guiados.
Execute o comando na máquina que consegue alcançar o seu servidor de base de dados. O --dsn é uma cadeia de ligação base que identifica o servidor, sem nome de base de dados — cada sincronização atribuída deriva dela a sua própria base de dados. Como todos os DSN, é armazenado localmente em modo-600 e nunca é enviado para a Entity Enricher.
ee-database host pair --server https://entityenricher.ai \ --dsn "postgres://user:pass@host:5432/" <token>
O emparelhamento verifica automaticamente os direitos de aprovisionamento do login (criar base de dados, DDL, DML) e falha de imediato perante uma permissão em falta. Prefere um login com privilégios mínimos? Adicione --admin-dsn e o aprovisionamento cria cada papel e base de dados em falta através da ligação de administração — o DSN de administração é usado apenas no momento do aprovisionamento, nunca armazenado.
ee-database host run
O host mantém um WebSocket de plano de controlo e reage às atribuições feitas na interface: escolha o host ao registar uma base de dados, ou mais tarde no separador Visão geral da base de dados. Cada sincronização atribuída é reivindicada, a sua base de dados é criada se não existir (em snake_case a partir do nome da sincronização; substitua por sincronização através de database_names no config.json do host), sendo depois sincronizada pelo ciclo comum abaixo.
Uma base de dados já emparelhada com outro cliente é reportada e ignorada — nunca é assumida. Revogar o host na interface corta o acesso da máquina de imediato, incluindo todas as credenciais por base de dados que reivindicou; as atribuições e os dados já sincronizados permanecem, pelo que um host reemparelhado retoma onde o anterior parou.
Os deltas saem do Entity Enricher através de uma caixa de saída FIFO rigorosa por base de dados. O servidor concede a janela visível durante 120 segundos e envia-a como um único lote; o cliente aplica todo o lote numa única transação e responde ack , o que faz avançar o cursor e aciona a próxima janela de imediato. Um cliente que falha a meio de um lote está protegido pela expiração da concessão e por um reenvio do lado do servidor — nada se perde nem é confirmado em duplicado.
O arranque inicial e o estado estável partilham o mesmo caminho de código. Ignore o arranque inicial com --skip-bootstrap se a sua base de dados já estiver preenchida.
Cada instrução transporta um _sync_revision para que uma linha mais antiga nunca substitua uma mais recente, mesmo fora de ordem.
Um erro de SQL reverte o lote e reporta o delta que falhou com a instrução problemática completa. O servidor coloca o lote desse enriquecimento em quarentena e reenvia a fila sem ele — o cliente continua a aplicar o resto. Só uma falha que não identifique nenhum delta termina com código diferente de zero.
Cada janela aplicada reporta a forma que escreveu, por tabela — pelo que dimensionar um re-enriquecimento noturno nunca exige arqueologia de logs sobre deltas já confirmados e removidos.
applying 12 delta(s) (10831 .. 10842) in one transaction applied 12 delta(s) in 84ms — 38 statement(s): mushroom 4 upserts, mushroom_common_names 12 upserts + 4 prunes, mushroom_human_uses 14 upserts + 4 prunes acked up to delta 10842
Um upsert corresponde a uma linha, pelo que as contagens são contagens de linhas; um prune é o único DELETE protegido por revisão que limpa as linhas filhas ou de junção que um novo payload deixou de reclamar. As linhas filhas são reconciliadas no local — nunca apagadas e reinseridas. Adicione --verbose para obter uma linha por delta, com o respetivo tipo de entidade, tempo decorrido e a sua própria forma.
O dialeto de destino é definido pelo registo da base de dados de schema no Entity Enricher — o cliente aplica o SQL que o servidor gerar. O PostgreSQL é o dialeto de lançamento; os renderizadores MySQL / MariaDB, SQL Server e Oracle estão previstos (o driver MySQL já vem incluído). A aplicação de múltiplas instruções é tratada por driver (protocolo simples do pgx, multiStatements no MySQL).
Partindo do princípio de que a base de dados de destino já existe, o login só precisa de CONNECT na base de dados e de USAGE + CREATE no schema de destino. (Desde o PostgreSQL 15, public deixou de conceder CREATE a todos por predefinição.)
Tudo o resto decorre da propriedade: é o próprio cliente que cria as tabelas de réplica, pelo que é o dono delas, e essa propriedade implica as leituras e escritas de que os deltas de dados precisam. A propriedade não é opcional — o feed inclui também instruções de migração (ALTER TABLE …, CREATE INDEX …) que o PostgreSQL restringe ao dono da tabela, e nenhuma combinação de permissões a substitui.
Se as tabelas da réplica já existirem com um proprietário diferente, a verificação prévia de permissões da execução continua a passar — o login pode criar tabelas novas —, mas o primeiro delta de migração falha. Transfira-as com ALTER TABLE … OWNER TO <login> (ou conceda ao login pertença na role proprietária) em vez de acrescentar permissões.
Uma instrução que a sua base de dados recuse — a causa habitual é um duplicado preexistente sob um novo índice único — não interrompe o fluxo. O lote é revertido, o cliente reporta o delta que falhou juntamente com a instrução problemática completa (nunca truncada), e o servidor coloca o lote desse enriquecimento em quarentena e reenvia a fila sem ele. O seu cliente continua a aplicar tudo o que se segue.
O trabalho em quarentena permanece listado no separador Quarentena da página Database Sync até que o resolva: corrija a causa na sua base de dados e faça a reinjeção — que reprojeta a entidade a partir do seu estado atual, em vez de repetir a instrução desatualizada — ou elimine-o se a linha já não for relevante.
Um bootstrap falhado é diferente: o snapshot é uma única transação, pelo que nada fica parcialmente aplicado, e o cliente guarda-o no diretório de perfil do emparelhamento como snapshot-failed.sql (modo 0600, substituído em cada tentativa, removido no sucesso seguinte), para que o possa inspecionar ou repetir com psql -f.
O cliente inicia o WebSocket através de :443/wss. O host da sua base de dados nunca aceita ligações de entrada — sem portas para abrir, sem ingress para configurar.
Uma credencial está associada a um único database sync. Emparelhar novamente rotaciona-a e remove instantaneamente a ligação ativa anterior.
O refresh token de 365 dias (armazenado em modo 600) é trocado por tokens de acesso de 15 minutos que autenticam o WebSocket. Revogar na interface desliga um cliente ativo em cerca de 1 segundo.
Um host gerido emparelha com uma chave curta eeh_… em vez de um JWT: o servidor guarda apenas o respetivo hash, ela nunca expira, e é a revogação do host na interface que lhe põe fim.
Um bloqueio por perfil impede que dois processos executem o mesmo emparelhamento em simultâneo — caso contrário, expulsariam ciclicamente a sessão WebSocket um do outro.
Execute o cliente com um role dedicado, limitado ao schema sincronizado, para que um token comprometido não possa tocar em mais nada — mas permita que esse role crie as tabelas de réplica, passando a ser o seu proprietário. As instruções de migração exigem propriedade, não permissões atribuídas.
| Comando | O que faz |
|---|---|
| ee-database pair --server URL | Emparelhamento por código de dispositivo confirmado no navegador. Escolha que base de dados sincronizar. |
| ee-database pair --server URL <token> | Emparelhe com um token emitido na página Database Sync (compatível com ambientes headless). |
| ee-database run --dsn DSN [--save-dsn] [--skip-bootstrap] | Faça o arranque inicial a partir do snapshot (a menos que seja ignorado) e, em seguida, ligue-se e aplique os deltas. |
| ee-database run … --create-missing | Criar primeiro a base de dados de destino quando esta não existir, utilizando as credenciais do próprio DSN (o postgres precisa de CREATEDB, o mysql do privilégio CREATE). |
| ee-database run … --create-missing --admin-dsn DSN | Inicialize tudo o que o DSN de destino nomeia através de uma ligação de administrador: o role/utilizador em falta (com a palavra-passe do DSN) e a base de dados de que é proprietário. O DSN de destino deixa então de necessitar de direitos de criação; o DSN de administrador nunca é armazenado. |
| ee-database run --all | Sincronizar todas as bases de dados emparelhadas em simultâneo a partir de um único processo (cada uma precisa de um DSN guardado). |
| ee-database run … --verbose | Regista a forma de escrita e o tempo decorrido de cada delta, e não apenas o resumo por janela. Também aceite por host run. |
| ee-database host pair --server URL --dsn BASE_DSN [--admin-dsn DSN] <token> | Emparelhe esta máquina uma vez como host de sincronização gerido — o DSN base identifica o seu servidor de base de dados (sem nome de base de dados) e nunca sai da máquina; o token vem da caixa de diálogo Sync hosts (o botão Sync hosts da barra de ferramentas na página Database Sync). Um emparelhamento por servidor: emparelhe com vários servidores Entity Enricher em paralelo. |
| ee-database host run [--server URL] | Modo gerido: cada sincronização de base de dados atribuída a este anfitrião é reclamada, criada se não existir e mantida sincronizada automaticamente — sem emparelhamento por base de dados, em todos os servidores emparelhados de uma só vez (--server limita a um). Uma base de dados já emparelhada com outro cliente é reportada, nunca assumida. |
| ee-database host status / host disconnect [--server URL] | Mostrar ou esquecer os emparelhamentos de anfitrião desta máquina. Revogue do lado do servidor a partir do cartão Anfitriões de sincronização. |
| ee-database status | Mostrar o estado do emparelhamento, o URL do servidor e as bases de dados emparelhadas. |
| ee-database disconnect | Esquecer as credenciais locais de um emparelhamento. Revogue no servidor a partir da interface. |
| ee-database version | Versão para impressão. |
As credenciais são guardadas em modo 600, um perfil por cada base de dados emparelhada, em ~/.config/ee-database/profiles/ — emparelhe uma vez por base de dados e use --database NAME para selecionar uma quando houver várias emparelhadas. Prefere não usar automatização nenhuma? O mesmo feed está disponível em REST simples: GET /api/databases//changes e depois POST /api/databases//ack — consulte Database Sync.
O cliente tem licença MIT e reside num repositório público, para que qualquer pessoa possa auditar exatamente o que é executado na sua base de dados.
Código-fonte: github.com/TOT-Concept/ee-database
Versões: github.com/TOT-Concept/ee-database/releases — cada binário é assinado com cosign antes da publicação.
Audite o instalador: curl -fsSL https://entityenricher.ai/install-eedatabase.sh | less