Le client d'application open-source pour les bases de données de schéma. Exécutez-le sur n'importe quelle machine pouvant atteindre votre propre PostgreSQL, appairez-le une fois, et il maintient cette base de données synchronisée avec vos enrichissements — en s'initialisant à partir d'un instantané, puis en appliquant un flux de deltas en direct via un unique WebSocket sortant. Votre chaîne de connexion ne quitte jamais cette machine.
Chaque instruction est protégée par révision, de sorte qu'un traitement par lot redistribué converge vers les mêmes lignes. Une erreur SQL annule le traitement par lot et l'interrompt — un delta corrompu n'est jamais ignoré silencieusement.
Le client récupère l'état, pas les opérations : chaque delta transporte la ou les lignes actuelles complètes d'une entité modifiée sous la forme d'un INSERT … ON CONFLICT … DO UPDATE idempotent, de sorte que la cible converge même si un traitement par lot a été manqué.
Les database syncs peuvent être consommés de plusieurs façons — n8n, Make.com, MCP, webhooks bruts ou le flux de deltas REST. Le client de synchronisation est la voie entièrement automatisée : le moins à développer et le moins à exposer.
Aucun scénario n8n, aucun cron, aucun code de liaison. Appairez une fois et le client s'amorce à partir de l'instantané, puis applique chaque delta dès son arrivée.
La chaîne de connexion est passée en ligne de commande ou stockée localement en mode 600 — elle n'est jamais envoyée à Entity Enricher. Le client ne se connecte que vers l'extérieur.
Chaque delta est un upsert idempotent, protégé par révision. Si le client s'arrête en plein traitement par lot, le traitement par lot est redistribué après l'expiration de son bail et sa réapplication converge vers les mêmes lignes.
Une erreur SQL annule le traitement par lot et signale le delta fautif. Le serveur met en quarantaine l'intégralité du traitement par lot de cet enrichissement et repousse la file sans lui : le client reste connecté et poursuit l'application — un seul enregistrement défectueux ne peut pas bloquer tout ce qui le suit, et le travail mis en quarantaine reste listé jusqu'à ce que vous le traitiez.
Enregistrez d'abord une base de données sur un schéma, puis appairez un client et exécutez-le sur une machine pouvant atteindre votre base de données.
Sur la page Database Sync, déclarez une base de données sur le schéma que vous souhaitez répliquer et vérifiez ses clés de base de données. Voir Database Sync pour le modèle complet. Cette étape déclare le dialecte cible que le client appliquera.
Collez ceci dans un terminal. Le script vérifie une signature cosign avant l'installation.
curl -fsSL https://entityenricher.ai/install-eedatabase.sh | sh
Windows : iwr -useb https://entityenricher.ai/install-eedatabase.ps1 | iex. Ou téléchargez un binaire signé depuis Releases, ou compilez depuis les sources (Go ≥ 1.23) : go build -o ee-database .
Le code source et les versions signées se trouvent sur TOT-Concept/ee-database (MIT).
Exécutez ee-database pair. Un onglet de navigateur s'ouvre sur /database/connect avec un code court — confirmez-le, et choisissez quelle base de données ce client doit synchroniser.
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...
Vous préférez un jeton ? Émettez-en un depuis la page Database Sync (Client de synchronisation → Appairer un client) et transmettez-le directement : ee-database pair --server … <refresh-token>.
Lors de la première exécution, le client récupère l'instantané .sql et l'applique, puis se connecte et diffuse les deltas. --save-dsn stocke la chaîne de connexion localement afin que les exécutions ultérieures ne nécessitent aucun argument.
Chaque exécution vérifie aussi automatiquement les droits de provisionnement de l'identifiant (créer une base de données, DDL, DML) et communique le résultat à la fiche du client de synchronisation, de sorte qu'une autorisation manquante est visible avant que les deltas n'échouent à s'appliquer. Si aucun schéma lié n'est encore publié, le client reste connecté et attend — la première publication démarre le flux d'elle-même, sans redémarrage nécessaire.
ee-database run --dsn "postgres://user:pass@localhost:5432/mydb" --save-dsn
« À côté » signifie adjacent au réseau, pas sur le serveur de base de données : toute machine ou tout conteneur pouvant atteindre le DSN convient — y compris PostgreSQL géré dans le cloud (Azure, OVHcloud, AWS RDS…), qui impose généralement TLS : …/mydb?sslmode=require.
Plusieurs bases de données sur une même machine ? Un hôte de synchronisation fait remonter d'un cran la cérémonie d'appairage : appairez la machine une seule fois, et chaque database sync que vous lui affectez est revendiquée, provisionnée et maintenue à jour automatiquement — enregistrer une nouvelle synchronisation ne demande plus jamais de session de terminal. Nécessite le client 1.5.0 ou une version ultérieure, qui s'appaire une fois par serveur et non une fois par machine — un même hôte peut ainsi servir plusieurs instances Entity Enricher côte à côte.
Sur la page Database Sync, cliquez sur le bouton Sync hosts de la barre d'outils et ajoutez un hôte portant le nom de la machine. Un jeton d'appairage à usage unique s'affiche une seule fois, intégré à une commande host pair à copier-coller, accompagnée d'étapes de configuration guidées.
Exécutez la commande sur la machine qui peut atteindre votre serveur de base de données. Le --dsn est une chaîne de connexion de base nommant le serveur, sans nom de base de données — chaque synchronisation assignée en dérive sa propre base de données. Comme tout DSN, il est stocké en mode 600 localement et n'est jamais envoyé à Entity Enricher.
ee-database host pair --server https://entityenricher.ai \ --dsn "postgres://user:pass@host:5432/" <token>
L'appairage vérifie automatiquement les droits de provisionnement de l'identifiant (créer une base de données, DDL, DML) et échoue immédiatement en cas d'autorisation manquante. Vous préférez un identifiant à privilèges minimaux ? Ajoutez --admin-dsn et le provisionnement crée alors chaque rôle et base de données manquants via la connexion administrative — le DSN administratif est utilisé uniquement au moment du provisionnement, jamais stocké.
ee-database host run
L'hôte détient un WebSocket de plan de contrôle et réagit aux assignations effectuées dans l'interface : choisissez l'hôte lors de l'enregistrement d'une base de données, ou plus tard dans l'onglet Aperçu de la base de données. Chaque synchronisation assignée est revendiquée, sa base de données créée si elle est absente (nom en snake_case à partir du nom de la synchronisation ; remplacez par synchronisation via database_names dans le config.json de l'hôte), puis synchronisée par la boucle ordinaire ci-dessous.
Une base de données déjà appairée avec un autre client est signalée et ignorée — jamais reprise. La révocation de l'hôte dans l'interface coupe instantanément la machine, y compris chaque identifiant par base de données qu'il avait revendiqué ; les assignations et les données déjà synchronisées sont conservées, de sorte qu'un hôte réappairé reprend là où l'ancien s'était arrêté.
Les deltas quittent Entity Enricher via une file d'attente sortante FIFO stricte, propre à chaque base de données. Le serveur loue la fenêtre visible pendant 120 secondes et la transmet en un seul lot ; le client applique l'ensemble du lot dans une seule transaction et répond ack , ce qui fait avancer le curseur et déclenche immédiatement la fenêtre suivante. Un client qui meurt en cours de lot est couvert par l'expiration du bail et une retransmission côté serveur — rien n'est perdu ni validé deux fois.
L'amorçage et le régime permanent partagent un seul chemin de code. Ignorez l'amorçage avec --skip-bootstrap si votre base de données est déjà initialisée.
Chaque instruction porte un _sync_revision afin qu'une ligne plus ancienne n'écrase jamais une plus récente, même dans le désordre.
Une erreur SQL annule le traitement par lot et signale le delta fautif avec l'intégralité de l'instruction en cause. Le serveur met en quarantaine le traitement par lot de cet enrichissement et repousse la file sans lui — le client continue d'appliquer le reste. Seule une erreur qui ne désigne aucun delta se termine avec un code non nul.
Chaque fenêtre appliquée indique la forme de ce qu'elle a écrit, table par table — ainsi, dimensionner un ré-enrichissement nocturne n'exige jamais de fouiller les logs à la recherche de deltas déjà acquittés et disparus.
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
Un upsert correspond à une ligne, donc les compteurs sont des nombres de lignes ; un prune est l'unique DELETE protégé par révision qui supprime les lignes enfants ou de jonction qu'une nouvelle charge utile ne revendique plus. Les enfants sont réconciliés sur place — jamais effacés puis réinsérés. Ajoutez --verbose pour obtenir une ligne par delta, avec son type d'entité, sa durée réelle et sa propre forme.
Le dialecte cible est fixé par l'enregistrement schéma–base de données dans Entity Enricher — le client applique le SQL généré par le serveur. PostgreSQL est le dialecte de lancement ; les moteurs de rendu MySQL / MariaDB, SQL Server et Oracle sont prévus (le pilote MySQL est déjà intégré). L'application multi-instructions est gérée par pilote (protocole simple pgx, multiStatements pour MySQL).
Si la base de données cible existe déjà, le compte de connexion n'a besoin que de CONNECT sur la base et de USAGE + CREATE sur le schéma cible. (Depuis PostgreSQL 15, public n'accorde plus CREATE à tout le monde par défaut.)
Tout le reste découle de la propriété : le client crée lui-même les tables de réplication, il en est donc propriétaire, et cette propriété implique les lectures et les écritures dont les deltas de données ont besoin. La propriété n'est pas optionnelle — le flux fournit aussi des instructions de migration (ALTER TABLE …, CREATE INDEX …) que PostgreSQL réserve au propriétaire de la table, et aucune combinaison de droits ne peut s'y substituer.
Si les tables du réplica existent déjà sous un propriétaire différent, le contrôle préalable des droits de l'exécution passe malgré tout — le login peut créer de nouvelles tables — mais le premier delta de migration échoue. Transférez-les avec ALTER TABLE … OWNER TO <login> (ou accordez au login l'appartenance au rôle propriétaire) plutôt que d'ajouter des privilèges.
Une instruction que votre base refuse — un doublon préexistant sous un nouvel index unique en est la cause habituelle — n'interrompt pas le flux. Le traitement par lot est annulé, le client signale le delta fautif ainsi que l'intégralité de l'instruction en cause (jamais tronquée), et le serveur met en quarantaine le traitement par lot de cet enrichissement puis repousse la file sans lui. Votre client continue d'appliquer tout ce qui suit.
Le travail mis en quarantaine reste listé dans l'onglet Quarantaine de la page Database Sync jusqu'à ce que vous le traitiez : corrigez la cause dans votre base de données puis réinjectez — ce qui reprojette l'entité depuis son état actuel au lieu de rejouer l'instruction périmée — ou abandonnez-le si la ligne n'a plus d'importance.
Un bootstrap en échec est un cas à part : le snapshot forme une seule transaction, rien n'est donc appliqué partiellement, et le client l'enregistre dans le répertoire de profil de l'appairage sous le nom snapshot-failed.sql (mode 0600, remplacé à chaque tentative, supprimé à la réussite suivante) afin que vous puissiez l'inspecter ou le rejouer avec psql -f.
Le client initie le WebSocket sur :443/wss. Votre hôte de base de données n'accepte jamais de connexions entrantes — aucun port à ouvrir, aucune entrée à configurer.
Un identifiant est lié à un seul database sync. Un nouvel appariement le régénère et expulse instantanément la connexion active précédente.
Le jeton de rafraîchissement de 365 jours (stocké en mode 600) est échangé contre des jetons d'accès de 15 minutes qui authentifient le WebSocket. Une révocation dans l'interface déconnecte un client actif en ~1 seconde.
Un hôte managé s'appaire avec une courte clé eeh_… plutôt qu'avec un JWT : le serveur n'en conserve que le hash, elle n'expire jamais, et seule la révocation de l'hôte dans l'interface y met fin.
Un verrou par profil empêche deux processus d'exécuter le même appairage en même temps — sans quoi ils s'expulseraient mutuellement de leur session WebSocket en boucle.
Exécutez le client sous un rôle dédié, restreint au schéma synchronisé, afin qu'un jeton compromis ne puisse rien atteindre d'autre — mais laissez ce rôle créer les tables de réplication pour qu'il en soit propriétaire. Les instructions de migration exigent la propriété, pas de simples droits.
| Commande | Ce que cela fait |
|---|---|
| ee-database pair --server URL | Appairage par code d'appareil confirmé dans le navigateur. Choisissez la base de données à synchroniser. |
| ee-database pair --server URL <token> | Appairage à l'aide d'un jeton émis sur la page Database Sync (compatible sans interface graphique). |
| ee-database run --dsn DSN [--save-dsn] [--skip-bootstrap] | Amorcez à partir de l'instantané (sauf si ignoré), puis connectez-vous et appliquez les deltas. |
| ee-database run … --create-missing | Créez d'abord la base de données cible si elle n'existe pas, en utilisant les identifiants du DSN lui-même (postgres nécessite CREATEDB, mysql le privilège CREATE). |
| ee-database run … --create-missing --admin-dsn DSN | Initialisez tout ce que désigne le DSN cible via une connexion admin : le rôle/utilisateur manquant (avec le mot de passe du DSN) et la base de données dont il est propriétaire. Le DSN cible n'a alors besoin d'aucun droit de création ; le DSN admin n'est jamais stocké. |
| ee-database run --all | Synchronisez toutes les bases de données appairées simultanément depuis un seul processus (chacune nécessite un DSN enregistré). |
| ee-database run … --verbose | Journalise la forme d'écriture et la durée réelle de chaque delta, et pas seulement le résumé par fenêtre. Également accepté par host run. |
| ee-database host pair --server URL --dsn BASE_DSN [--admin-dsn DSN] <token> | Appairez cette machine une fois comme hôte de synchronisation géré — le DSN de base désigne votre serveur de base de données (sans nom de base) et ne quitte jamais la machine ; le jeton provient de la boîte de dialogue Sync hosts (le bouton Sync hosts de la barre d'outils sur la page Database Sync). Un appairage par serveur : appairez plusieurs serveurs Entity Enricher en parallèle. |
| ee-database host run [--server URL] | Mode géré : chaque database sync affecté à cet hôte est revendiqué, créé s'il est absent et maintenu synchronisé automatiquement — aucun appairage base par base, sur tous les serveurs appairés à la fois (--server limite à un seul). Une base de données déjà appairée avec un autre client est signalée, jamais reprise. |
| ee-database host status / host disconnect [--server URL] | Affichez ou oubliez les appairages d'hôte de cette machine. Révoquez-les côté serveur depuis la carte Hôtes de synchronisation. |
| ee-database status | Affichez l'état de l'appairage, l'URL du serveur et les bases de données appairées. |
| ee-database disconnect | Oubliez les identifiants locaux d'un appairage. Révoquez côté serveur depuis l'interface. |
| ee-database version | Version imprimable. |
Les identifiants sont stockés en mode 600, un profil par base appairée, sous ~/.config/ee-database/profiles/ — l'appairage se fait une fois par base, et --database NAME permet d'en sélectionner une lorsque plusieurs sont appairées. Vous préférez vous passer totalement d'automatisation ? Le même flux est disponible en REST simple : GET /api/databases//changes puis POST /api/databases//ack — voir Database Sync.
Le client est sous licence MIT et se trouve dans un dépôt public, afin que chacun puisse auditer exactement ce qui s'exécute sur sa base de données.
Source : github.com/TOT-Concept/ee-database
Versions : github.com/TOT-Concept/ee-database/releases — chaque binaire est signé avec cosign avant publication.
Auditez l'installateur : curl -fsSL https://entityenricher.ai/install-eedatabase.sh | less