Fondations de la plateforme
Libre WebUI prend en charge un profil solo privilégiant l'exécution locale et un profil team
partagé. Le profil solo utilise SQLite, des objets binaires locaux chiffrés, des vecteurs intégrés chiffrés, une
coordination locale et un worker durable intégré. Le profil équipe utilise PostgreSQL,
des objets binaires privés compatibles S3, PGVector, une coordination Redis et un worker
durable externe. Le démarrage rejette les profils mixtes au lieu de répartir silencieusement
l'état entre des serveurs locaux et partagés.
Étape actuelle
| Domaine | Fondations mises en œuvre | Travail restant pour les appelants |
|---|---|---|
| Persistance | Dépôts SQLite et PostgreSQL, migrations immuables, transactions groupées | Les nouveaux domaines doivent respecter les limites des dépôts |
| Objets binaires | Stockages locaux et compatibles S3 chiffrés en flux, plages, sommes de contrôle et quotas durables | Migrer les pièces jointes de chat, avatars et autres champs binaires encore intégrés |
| Vecteurs | Vecteurs intégrés chiffrés, ACL PGVector et reconstruction d'index documentaire sûre après suppression | Les nouveaux appelants de plongements doivent préserver le même contrat d'autorité et de cycle de vie |
| Coordination | Événements locaux et Redis, cache, baux, limites de débit, invalidation et état | Redis ne doit jamais faire autorité |
| Tâches/événements | Files SQLite/PostgreSQL, événements transactionnels, workers, nouvelles tentatives, annulation, administration | Chaque nouvel effet de bord exige une conception idempotente ou une boîte d'envoi |
| Exploitation | Barrières d'état, archives de sauvegarde signées et chiffrées, restauration sur cible propre, vérification | Tester la restauration et l'acceptation entre répliques pour chaque environnement de déploiement |
Profils d'environnement d'exécution
LIBRE_PLATFORM_MODE=solo est la valeur par défaut. Elle sélectionne SQLite, les objets binaires locaux,
les vecteurs intégrés, la coordination locale et le worker durable intégré. Redis
peut être sélectionné en mode solo, mais cela ne rend ni SQLite ni les fichiers locaux
sûrs pour un partage entre répliques.
LIBRE_PLATFORM_MODE=team exige toutes les dépendances partagées à la fois :
DATABASE_BACKEND=postgresavecDATABASE_URL;BLOB_STORE_BACKEND=s3;VECTOR_STORE_BACKEND=pgvector;COORDINATION_BACKEND=redisavecREDIS_URL; etJOB_WORKER_MODE=external.
Ces sélecteurs forment un ensemble cohérent. Le démarrage en mode équipe échoue si une dépendance partagée manque ou si un serveur local est introduit dans le profil.
Migrer une installation solo existante
Arrêtez toutes les applications et tous les workers Libre avant la migration. Les exemples utilisent la
commande libre-webui installée globalement par npm ou Homebrew. Sans installation
globale, remplacez-la par npx --yes libre-webui@latest. Depuis une copie des sources,
compilez une fois, puis remplacez libre-webui migrate-postgres par
npm run migrate:postgres --. Configurez l'environnement PostgreSQL, S3 et de clé de chiffrement
versionnée cible exactement comme dans le déploiement équipe visé, puis commencez par l'analyse en lecture seule :
libre-webui migrate-postgres \
--source /absolute/path/to/data.sqlite \
--plugins /absolute/path/to/plugins \
--mode dry-run
N'appliquez la migration qu'à la cible vide indiquée par ce rapport. Une exécution qui échoue laisse un journal d'importation avec somme de contrôle ; reprenez cette même source et cette même cible au lieu de démarrer une importation sans rapport :
libre-webui migrate-postgres \
--source /absolute/path/to/data.sqlite \
--plugins /absolute/path/to/plugins \
--mode apply
# Only after an interrupted apply of this exact source and target:
libre-webui migrate-postgres \
--source /absolute/path/to/data.sqlite \
--plugins /absolute/path/to/plugins \
--mode apply --resume
libre-webui migrate-postgres \
--source /absolute/path/to/data.sqlite \
--plugins /absolute/path/to/plugins \
--mode validate
Le marqueur d'achèvement n'est écrit qu'après le transfert et l'authentification dans
PostgreSQL/S3/PGVector des lignes relationnelles, définitions d'extensions, objets binaires locaux chiffrés,
vecteurs intégrés et anciens vecteurs de personas. La commande n'invente jamais de clé de
chiffrement source : ENCRYPTION_KEY doit correspondre au fichier .encryption_key source, et
STORAGE_ENCRYPTION_KEYS doit contenir la clé active configurée ainsi que l'entrée legacy
correspondante.
Exécuter le profil équipe inclus
Partez du modèle fourni qui échoue de manière fermée. Conservez le fichier d'environnement rempli hors du dépôt et limitez son accès à la personne qui exploite le système :
cp deploy/team/.env.example /absolute/path/to/libre-team.env
chmod 600 /absolute/path/to/libre-team.env
Remplacez toutes les valeurs REPLACE_* avant le démarrage. Générez le mot de passe PostgreSQL
avec un alphabet sûr pour les URL (par exemple openssl rand -hex 32), car la même valeur littérale
sert à la fois de mot de passe du serveur et de partie de DATABASE_URL.
ENCRYPTION_KEY et chaque valeur de STORAGE_ENCRYPTION_KEYS doivent comporter
exactement 64 caractères hexadécimaux. Sur une nouvelle installation, l'entrée legacy doit
être identique à ENCRYPTION_KEY ; pour une migration SQLite, les deux doivent correspondre à la clé source.
Utilisez une autre clé active pour les nouvelles écritures d'objets binaires et conservez les anciennes jusqu'à
ce que l'inventaire des objets prouve qu'elles ne sont plus utilisées.
Le même fichier peut définir POSTGRES_MIGRATION_MODE, POSTGRES_POOL_MAX, les
délais PostgreSQL pris en charge, REDIS_CONNECT_TIMEOUT_MS, OLLAMA_BASE_URL,
OLLAMA_TIMEOUT, OLLAMA_LONG_OPERATION_TIMEOUT et OLLAMA_MAX_CONTEXT ;
l'environnement Compose partagé transmet chaque valeur de manière identique à l'application et au worker externe.
Les délais des fournisseurs acceptent 1,000-3,600,000 millisecondes, le contexte maximal accepte
128-2,097,152 jetons, et le délai long ne peut pas être inférieur au délai standard ;
des valeurs mal formées font échouer les deux points d'entrée serveur avant la création de tout état.
Les binaires Agent CLI propres à un nœud et les fichiers de jetons OAuth Codex ne sont pas pris en charge par
les workers durables externes ; le profil équipe désactive donc ces deux parcours de fournisseurs et le démarrage
rejette toute tentative de les activer. Démarrez ensuite les répliques de l'application, le worker durable externe,
PostgreSQL/PGVector, Redis, le bucket MinIO avec gestion des versions et la passerelle :
docker compose --env-file /absolute/path/to/libre-team.env \
-f docker-compose.team.yml up --build --scale libre-webui=3 -d
docker compose --env-file /absolute/path/to/libre-team.env \
-f docker-compose.team.yml ps
Le profil équipe de base ne monte volontairement aucun socket Docker ; Work adossé à Docker est donc indisponible. Activez-le uniquement en ajoutant la surcouche de production fournie à chaque commande du cycle de vie :
docker compose --env-file /absolute/path/to/libre-team.env \
-f docker-compose.team.yml -f docker-compose.team.work.yml \
up --build --scale libre-webui=3 -d
docker compose --env-file /absolute/path/to/libre-team.env \
-f docker-compose.team.yml -f docker-compose.team.work.yml ps
Cette surcouche dirige les processus de l'application et du worker vers un unique proxy de socket Docker filtré sur un réseau strictement interne. Aucun des deux processus ne reçoit le socket brut ni l'appartenance à son groupe, et les espaces de travail Work sous forme de dossiers de l'hôte restent désactivés. Le proxy n'expose que les informations, images, conteneurs, appels exec, volumes, réseaux et méthodes d'écriture nécessaires à ces opérations du cycle de vie. Cela réduit la surface de l'API, mais ne fait pas de Docker une frontière entre locataires : la création de conteneurs peut toujours monter des chemins de l'hôte. Utilisez une machine virtuelle dédiée ou un démon Work sans root ou distinct lorsque l'isolation de l'hôte est importante.
N'exposez pas directement les services PostgreSQL, Redis ou MinIO appartenant à Compose. Pour les dépendances gérées, utilisez le profil équipe Helm et conservez un TLS vérifié ; le fichier Compose ne désactive TLS pour PostgreSQL que sur son réseau privé de projet. L'état de disponibilité reste négatif jusqu'à la présence d'un worker externe.
Limite de persistance et de migration
L'identité et l'autorisation utilisent désormais des dépôts asynchrones. La fonction de rappel de transaction du dépôt reçoit une unité de travail liée à la même connexion de base de données ; l'utilisation du dépôt global dans cette fonction est rejetée. Cette limite de transaction est employée par le pool de connexions PostgreSQL tout en préservant le comportement actuel de SQLite.
Le coordinateur de migration SQLite n'adopte les installations existantes qu'après avoir validé le schéma requis. Il consigne un numéro, un nom et une somme de contrôle de migration, les vérifie à chaque démarrage, rejette les journaux plus récents, inconnus ou divergents et fait échouer le démarrage lorsque la migration ou la validation du schéma échoue. L'état de disponibilité et l'inventaire de restauration utilisent le même contrat d'inspection canonique.
Avant d'importer les services d'application avec état, le démarrage copie la base SQLite existante
et les fichiers WAL/SHM actifs dans un répertoire temporaire privé, puis valide cette copie.
PLATFORM_PREFLIGHT_TMP_DIR doit disposer d'assez d'espace libre pour la base et son WAL.
Les déploiements Docker et Helm fournis y montent un stockage temporaire dédié sur disque ; le démarrage
ne dépend pas du tmpfs /tmp limité. Une ancienne clé de chiffrement absente ou un répertoire de données
historique imbriqué bloque le démarrage avant qu'une clé, une base ou un état d'extension de remplacement
ne puisse être créé.
Le schéma v4 ajoute un jeton d'égalité à clé pour les adresses e-mail d'identité chiffrées. La restauration
exige que chaque jeton soit présent et corresponde à son adresse e-mail authentifiée. Le démarrage
accepte un jeton absent avec une adresse authentifiée ou une valeur ancienne qui n'est pas une enveloppe pendant
l'étroite fenêtre de panne suivant la validation de la v4, afin que l'initialisation du dépôt puisse terminer
le remplissage du chiffrement et des jetons. Les anciennes versions acceptaient n'importe quelle chaîne d'adresse e-mail et
utilisaient une valeur vide pour effacer le champ ; l'adoption préserve les valeurs non vides et normalise les
valeurs vides en NULL. Les valeurs endommagées qui ressemblent à une enveloppe et toute divergence non nulle
font toujours échouer le contrôle préalable.
Les services de l'application utilisent des dépôts asynchrones adaptés au dialecte. SQLite natif est limité
aux adaptateurs SQLite, à l'inspection de migration ou de restauration et aux contrôles d'état injectés
explicitement. Le stockage d'exécution est initialisé depuis la Persistence sélectionnée ; l'activation de PostgreSQL
ne se rabat jamais sur le singleton SQLite ni sur les anciens fichiers JSON dépendant du répertoire courant.
L'environnement commun des tâches durables reste lui aussi indépendant du pilote. L'autorisation de l'acteur
est lue au moyen du dépôt d'identités sélectionné, tandis que la construction du dépôt natif de tâches
est confinée à une unique limite de composition des adaptateurs. Les éditeurs transactionnels de domaine
reçoivent un exécuteur synchrone opaque dans SQLite et un exécuteur lié à la transaction dans PostgreSQL ;
ils ne reçoivent jamais de handle better-sqlite3. Le test de limite de persistance rejette les handles
de pilotes natifs dans les contrats communs de tâches, ressources, identités, chats et Work.
Fondations du stockage des objets binaires et des vecteurs
Les médias générés de la galerie et les fichiers sources des documents utilisent BlobStore ; la RAG documentaire
et la mémoire des personas utilisent VectorStore. Les anciennes lignes de galerie SQLite sont lues selon les
deux formats et adoptées comme références d'objets lors du premier accès. Les métadonnées relationnelles
et une référence durable font autorité ; les URL de fournisseurs et les clés S3 physiques ne sont jamais
conservées comme contenu de l'application. Les pièces jointes de chat, les avatars et les autres champs binaires encore
intégrés n'utilisent pas encore le stockage d'objets et ne doivent pas être présentés comme migrés.
La barrière de restauration authentifie chaque objet durable et enveloppe de vecteurs intégrés séquentiellement
sous des limites agrégées explicites. Elle authentifie aussi strictement les enveloppes texte anciennes reconnaissables
et chaque enveloppe binaire de voix enregistrée avec l'ENCRYPTION_KEY de l'application ; elle n'utilise
jamais la solution de compatibilité à l'exécution qui déchiffre puis renvoie l'original. Elle n'initialise,
ne répare, ne réécrit ni ne supprime le stockage source ; un texte chiffré corrompu, des clés inconnues ou
incorrectes, des dispositions d'objets non canoniques et le dépassement des limites de vérification bloquent
l'instantané.
Les limites de restauration par défaut sont de 250,000 objets locaux, 64 GiB d'octets chiffrés et en clair
pour les objets binaires, 250,000 lignes de vecteurs, 4 GiB de texte chiffré vectoriel sérialisé et
500 millions de composantes vectorielles. Les tests et les appelants intégrés peuvent remplacer les limites
pour chaque exécution au moyen de RecoveryInventoryOptions ; l'interface en ligne de commande n'échantillonne ni
n'ignore jamais silencieusement l'état excédentaire.
La vérification des anciens textes chiffrés accepte par défaut un million de champs candidats remplis et 16 GiB chacun pour l'ensemble des octets enregistrés et du texte en clair authentifié. Les lignes en clair des anciennes générations du schéma restent compatibles, car les enveloppes texte anciennes ne possèdent aucun marqueur durable ; le rapport ne compte que les enveloppes authentifiées. Les enveloppes de voix enregistrées sont sans ambiguïté et s'authentifient toujours avec l'identité du profil, du propriétaire et du champ comme données supplémentaires.
Objets binaires locaux chiffrés
BlobStore est limité au propriétaire et expose l'écriture et la lecture en flux, les métadonnées et statistiques,
les plages d'octets inclusives et la suppression idempotente. LocalEncryptedBlobStore
écrit des objets opaques identifiés par UUID sous une racine fournie par l'application ; la
cible d'intégration est ${DATA_DIR}/blobs. Il utilise des fichiers temporaires exclusifs,
fsync et un renommage atomique sur le même système de fichiers, avec des répertoires 0700 et des fichiers 0600.
Chaque objet dispose d'une clé de données aléatoire de 256 bits. AES-256-GCM chiffre les métadonnées privées et authentifie indépendamment des segments de corps bornés. Les données authentifiées supplémentaires lient l'identifiant de l'objet, le propriétaire, l'usage, l'indice du segment et la longueur en clair. Le trousseau de clés de stockage versionné enveloppe chaque clé de données. Le descripteur consigne la taille en clair, la somme SHA-256, le type de contenu, l'heure de création, la version du format et l'identifiant de la clé de chiffrement. Les lectures complètes vérifient SHA-256 ; les lectures par plage authentifient chaque segment touché.
Le contrat de quota réserve de la capacité avant la diffusion, consomme le nombre réel d'octets,
ne valide qu'après la visibilité atomique et libère les réservations qui échouent. SQLite utilise
BEGIN IMMEDIATE ; PostgreSQL emploie des transactions sérialisables et des verrous de lignes. Les métadonnées
des objets S3 et l'utilisation du quota sont validées ou annulées dans une même transaction de base de données.
Au démarrage, les réservations expirées et les objets de quota dont l'objet physique manque sont harmonisés.
BLOB_QUOTA_BYTES_PER_USER définit la limite durable par propriétaire et
BLOB_QUOTA_RESERVATION_TTL_MS borne les réservations abandonnées.
BLOB_STORE_BACKEND=s3 utilise un bucket privé compatible S3. Libre téléverse
des clés d'objets opaques et des flux de segments chiffrés par l'application, conserve les descripteurs
chiffrés dans PostgreSQL, prend en charge les plages HTTP inclusives, vérifie les condensats SHA-256 du
texte en clair et du texte chiffré et effectue une suppression idempotente. Une ligne en cours de suppression reste
durable jusqu'à ce que la suppression physique et le retrait atomique des métadonnées et du quota réussissent ;
l'harmonisation retente les suppressions interrompues et retire les objets physiques orphelins anciens. La suite
MinIO soumise à Docker couvre la lecture et la suppression entre répliques, l'isolation des locataires, la concurrence
sur les quotas, les flux non consommés et les défaillances de base de données injectées aux limites de validation
et de suppression.
Vecteurs intégrés chiffrés
VectorStore exige un acteur pour chaque requête et chaque mutation. Les enregistrements portent un
espace de noms, un identifiant opaque limité au locataire, un propriétaire, un identifiant de ressource, le modèle de plongements,
les dimensions, la version, la révision source, les attributs d'égalité et d'éventuels droits utilisateur ou groupe.
SQLite applique les prédicats d'espace de noms, modèle, dimension, version, propriétaire ou droit, ressource et attribut avant que les plongements chiffrés ne quittent la base. Seul cet ensemble borné de candidats autorisés est déchiffré et classé par similarité cosinus. Un même identifiant vectoriel opaque est isolé par propriétaire sans révéler l'existence d'un autre locataire. Les insertions ou mises à jour remplacent les plongements, ACL et attributs atomiquement ; les suppressions sont limitées au propriétaire et se propagent aux lignes associées.
Les plongements utilisent AES-256-GCM, avec les métadonnées d'identité et de modèle liées comme données authentifiées supplémentaires. L'identité, les droits, le modèle, la version, la révision et les métadonnées de filtre interrogeables restent en clair ; les appelants ne doivent donc pas placer de secrets dans les attributs de filtre. Les plongements eux-mêmes constituent des données dérivées sensibles.
VECTOR_STORE_BACKEND=pgvector applique les prédicats d'espace de noms, modèle, dimensions, version,
ressource, attribut, propriétaire et droit dans la même instruction SQL que le classement par distance
et LIMIT. Le post-filtrage des plus proches voisins globaux est interdit. L'autorisation de groupe
est résolue à partir d'un résolveur fiable des appartenances actuelles pour chaque requête ; les groupIds
fournis par l'appelant sont ignorés. La révocation est donc immédiate et les fausses revendications de groupe
ne peuvent pas récupérer de candidats.
L'ingestion de documents et le point de terminaison de maintenance qui régénère les plongements capturent une spécification d'exécution immuable avant le début du travail : état d'activation, modèle, version du vecteur, version du découpeur, taille des segments, chevauchement et seuil de similarité. La même spécification contrôle la génération des segments, la publication relationnelle, l'insertion ou mise à jour des vecteurs et la requête sémantique ; modifier une préférence pendant une exécution ne peut produire des segments issus de modèles différents ni interroger un vecteur avec un autre seuil. Les métadonnées publiées du document consignent la révision agrégée des segments et cette spécification, afin que SQL reste le manifeste d'index faisant autorité.
La régénération détient un bail de coordination renouvelé automatiquement pour chaque document et revérifie la ligne limitée au propriétaire ainsi que sa pierre tombale de suppression permanente avant la publication relationnelle, puis avant et après la mutation des vecteurs. Une suppression peut être validée pendant qu'une insertion ou mise à jour est en cours ; le contrôle d'autorité qui suit retire alors les vecteurs recréés. Les lectures sémantiques PostgreSQL en mode équipe ne modifient jamais PGVector. SQLite peut republier paresseusement les plongements relationnels uniquement lorsque le manifeste enregistré prouve la correspondance exacte du modèle actuel et de la configuration des segments ; cette mutation facultative recharge la ligne et les segments tout en conservant le même bail du document. Une révision occupée ou remplacée est ignorée et reste admissible au repli sur la recherche par mots-clés ou à une régénération explicite.
Les index de documents sont remplacés par lots compensés d'au plus 1,000 vecteurs, et les contrôles d'index exacts parcourent par pages le manifeste complet de la ressource au lieu de supposer qu'un lot de mutation représente tout le document. Un document peut publier au maximum 100,000 segments, de sorte qu'aucun document ne dépasse le plafond total de segments documentaires de l'archive portable. L'ingestion rejette le 100,001e segment avant la génération des plongements ou la publication relationnelle ou vectorielle, et place cette tâche durable dans la file des échecs définitifs sans nouvelle tentative ; augmentez la taille des segments de plongements ou supprimez les sauts de paragraphe excessifs avant de téléverser à nouveau.
Les bases solo antérieures au manifeste peuvent contenir des vecteurs documentaires intégrés authentifiés sans aucune information sur le modèle ou le découpeur qui les a créés. La première utilisation sémantique ne considère que leur présence comme signal de mise à niveau : elle redécoupe le texte documentaire faisant autorité et régénère chaque vecteur selon la spécification actuelle capturée, tout en conservant le bail du document. Elle ne copie jamais l'ancienne charge utile et ne lui attribue pas la préférence actuelle. Une défaillance du fournisseur ou un bail occupé laisse l'ancienne ligne intacte et disponible pour la recherche par mots-clés.
La migration SQLite vers le mode équipe échoue de manière fermée lorsqu'un tel document ancien n'est pas entièrement
couvert par les métadonnées authentifiées du manifeste actuel et par un index exact de vecteurs de plateforme chiffrés.
Les préférences actuelles ne prouvent pas le modèle d'un vecteur historique. Lorsque la simulation signale ce blocage,
démarrez la version actuelle en mode solo/SQLite avec les mêmes DATA_DIR et ENCRYPTION_KEY,
activez et sélectionnez le modèle de plongements souhaité, utilisez Paramètres -> Documents -> Régénérer
les plongements pour chaque propriétaire concerné, puis relancez la simulation de migration. Ce n'est
qu'ensuite que les lectures du dépôt équipe peuvent ignorer le texte chiffré intégré conservé pendant que les
vecteurs prouvés sont déplacés vers PGVector.
La confidentialité diffère selon le serveur. SQLite intégré chiffre les plongements avec AES-256-GCM au niveau de l'application après application des prédicats ACL de métadonnées. PGVector doit travailler sur le plongement numérique et ne chiffre donc pas cette colonne au niveau de l'application. Traitez les plongements comme des données dérivées sensibles : exigez TLS, des volumes et sauvegardes PostgreSQL chiffrés, un rôle d'application aux privilèges minimaux, une administration restreinte de la base et des journaux SQL qui n'incluent jamais le vecteur ni le contenu source. Le texte source, le contenu de mémoire des personas, les métadonnées de galerie et les descripteurs d'objets restent chiffrés dans des enveloppes. Les attributs vectoriels sont interrogeables en clair et ne doivent jamais contenir de secrets.
Clés de chiffrement du stockage
Pendant la période actuelle de migration des appelants, les déploiements qui activent un trousseau de clés
versionné doivent définir une ENCRYPTION_KEY stable de 64 caractères, inclure cette même clé
dans l'entrée exacte legacy de STORAGE_ENCRYPTION_KEYS et définir
STORAGE_ENCRYPTION_ACTIVE_KEY_ID sur une entrée. Les écritures emploient la clé active ;
les lectures acceptent tous les identifiants configurés afin de permettre une rotation progressive. Cette exigence
temporaire liée à l'ancienne clé empêche le service de chiffrement existant de créer indépendamment
une autre clé. Conservez les anciennes clés jusqu'à ce que chaque objet et vecteur ait été réécrit ou
réenveloppé et vérifié.
En l'absence de cette table, l'adaptateur accepte l'ENCRYPTION_KEY existante de 64 caractères
sous l'identifiant legacy, ou lit le fichier ${DATA_DIR}/.encryption_key existant lorsque la clé
d'environnement est absente. La fabrique de stockage n'accepte qu'un fichier de clé ordinaire, non symbolique,
doté d'autorisations privées ; elle ne crée, ne réécrit ni ne remplace jamais ce fichier. Si la
configuration explicite de l'environnement contredit la clé persistante, le démarrage échoue de manière fermée.
Pendant une rotation, une ancienne clé d'environnement ou de fichier détectée doit rester dans la table versionnée
sous l'identifiant exact legacy jusqu'à la réécriture et la vérification des anciennes enveloppes. Toute clé
absente, mal formée, divergente ou inconnue provoque un échec fermé.
Les requêtes de vecteurs intégrés appliquent les prédicats ACL et de métadonnées dans SQLite, puis agrègent le nombre de candidats, les octets chiffrés et le travail de classement par nombre de dimensions avant de renvoyer le moindre texte chiffré à Node pour déchiffrement. Toute requête qui dépasse un budget échoue de manière fermée et doit être restreinte par ressource ou portée de métadonnées.
Coordination
Le contrat du coordinateur fournit des événements, des entrées de cache avec expiration, des baux clôturés et la consommation d'une limite de débit à fenêtre fixe. L'implémentation locale est réservée au profil solo à une seule réplique. L'implémentation Redis utilise des clients distincts pour les commandes et les abonnements, des charges utiles bornées, des contrôles d'état, des espaces de noms de clés, des scripts atomiques, des jetons de propriétaire uniques, l'expiration des baux et des jetons de clôture. Elle ne revient jamais à la coordination locale après une erreur Redis.
Redis ne fait pas autorité. Les autorisations, les tâches durables et les événements rejouables doivent rester dans la base de données ; Redis est une couche de réveil, d'invalidation du cache, de présence, de quota et de coordination. Le travail critique doit également valider son bail de base de données ou son jeton de clôture avant de valider un effet de bord.
La billetterie de l'application, les caches, l'invalidation partagée, les limites de connexion, les événements Work et les verrous distribués d'environnement d'exécution utilisent cette limite. Sélectionner Redis seul ne rend toujours pas la persistance locale partageable ; le mode équipe exige l'intégralité du profil partagé.
Tâches et événements durables
La migration SQLite v3 fournit les tables des tâches durables, tentatives, têtes de flux d'événements et événements ordonnés. Le contrat de service prend en charge la mise en file idempotente, les nouvelles tentatives bornées, l'annulation, la progression, le battement de cœur et la récupération des baux, l'état d'échec définitif et le rejeu par curseur global. Les charges utiles JSON chiffrées utilisent le trousseau de la plateforme, avec l'identité de la tâche ou de l'événement comme données authentifiées ; les références des charges utiles sont des identifiants opaques bornés.
La migration SQLite v13 et la migration PostgreSQL v12 ajoutent l'index correspondant
(stream_id, subject_id, global_cursor) utilisé pour le rejeu du chat limité à la génération.
Les filtres de flux et de sujet sont appliqués avant la limite de rattrapage : les générations antérieures
d'une longue session ne consomment donc pas le budget de rejeu de la génération actuelle et n'imposent pas
un parcours intégral du flux d'événements.
Les démarrages de l'application et du worker autonome enregistrent des gestionnaires audités pour l'ingestion de documents, la poursuite des médias et le nettoyage de ressources pouvant être retenté. La limite d'administration expose une inspection et une annulation bornées. La mise en file est idempotente, et les parcours relationnels de création ou suppression insèrent leur tâche durable dans la même transaction SQLite ou PostgreSQL. Le nettoyage des ressources retire les vecteurs, objets privés, références durables, entrées de cache et travaux en attente ciblant la ressource au moyen d'opérations sûres pour les nouvelles tentatives.
L'inventaire de restauration compte chaque état de tâche et résultat de tentative, consigne les flux d'événements et leur dernier curseur, bloque le travail en cours dangereux et authentifie les charges utiles chiffrées sous des limites agrégées. Il rejette également les incohérences de tête de flux et les séquences non contiguës par flux.
Les jetons de bail monotones empêchent les workers obsolètes de valider ultérieurement dans la base. La clôture ne garantit pas une exécution exactement une fois : un worker peut terminer un effet de bord externe et échouer avant d'enregistrer la réussite. L'adoption d'un gestionnaire exige donc des clés d'idempotence du fournisseur ou un protocole transactionnel de boîte d'envoi ou de réception, ainsi qu'une nouvelle validation de l'autorisation de l'acteur immédiatement avant chaque effet de bord.
La migration SQLite v4 ajoute un jeton unique de recherche d'adresse e-mail à clé à côté du texte chiffré aléatoire de l'identité. Ce jeton est un HMAC sous la clé de chiffrement de l'application : il restaure l'application atomique de l'unicité des adresses sans stocker de texte en clair ni employer un chiffrement déterministe. Au démarrage, chaque ancienne adresse e-mail d'identité est authentifiée et complétée avant l'acceptation du trafic.
État et restauration
Les sondes de déploiement distinguent maintenant la vie du processus de la disponibilité des dépendances :
/healthet/health/livene vérifient que le processus ;/health/readyvérifie la base de données, le journal canonique du schéma, l'écriture du stockage des données et les dépendances requises enregistrées tout en masquant les détails. Il n'attend pas les fournisseurs facultatifs ; et/health/deepexige un administrateur actuel et exécute les contrôles d'intégrité et de clés étrangères SQLite dans un worker borné hors de la boucle d'événements HTTP. Il agrège également en avertissements les sondes facultatives de fournisseurs au niveau du serveur, comme Ollama, sans modifier la disponibilité essentielle.
Exécutez libre-webui recovery-check --json ; depuis une copie des sources, compilez une fois le
serveur et utilisez npm run recovery:check -- --json. L'inventaire est en lecture seule et indique
les identités du schéma et des clés, la racine locale des objets binaires, le nombre d'anciens vecteurs et de vecteurs
de plateforme ; il authentifie le texte chiffré des objets et vecteurs locaux de plateforme, de l'ancienne application,
des voix enregistrées et des charges utiles chiffrées des tâches et événements durables. Il indique aussi les tailles
des données, les définitions d'extensions et leur présence éventuelle dans la racine de sauvegarde, les médias intégrés,
les ressources Work et leurs libellés de propriété exacts, les points de contrôle des tâches, tentatives et événements,
les exécutions, aperçus et tâches actifs, les blocages et les exclusions connues. Il s'agit d'une barrière préalable
à la sauvegarde, pas d'une sauvegarde complète. Consultez
Préparation à la restauration.
Fonctionnement certifié à plusieurs répliques
Le profil équipe est certifié pour au moins trois répliques de l'application et au moins un worker durable
externe, à condition que toutes les dépendances partagées soient configurées ensemble : PostgreSQL, PGVector,
Redis, objets binaires compatibles S3, secrets partagés stables et JOB_WORKER_MODE=external.
Le chart Helm impose ces prérequis lors du rendu : un nombre de répliques supérieur à un sans le profil
équipe complet fait échouer le rendu au lieu de déployer une topologie dangereuse. Les migrations de schéma
élisent un unique responsable au moyen d'un verrou consultatif PostgreSQL afin que des répliques de versions
différentes ne se disputent jamais le journal.
La certification est exécutable, pas déclarative : le pipeline de publication exécute un exercice à trois
répliques (npm run test:team-platform) qui construit l'image réelle et teste la reprise de flux entre
répliques, la mort d'un worker au milieu d'une écriture avec rejeu déterministe, le repli d'une panne Redis
sur le SQL faisant autorité, l'application des révocations pendant la perte du coordinateur, la cohérence des
limites de débit partagées, les nouvelles tentatives de suppression S3 et l'isolation des locataires sous charge.
Les personnes qui exploitent le système peuvent renforcer les pods avec secrets.existingSecret (référence à un Secret
géré par l'opérateur au lieu de rendre les valeurs du chart dans un nouveau Secret) et
networkPolicy.enabled (refus par défaut des entrées en dehors du port de l'application ; le worker durable
n'accepte aucune entrée). Les paramètres de sécurité des pods restent stricts dans tous les cas : utilisateur non-root,
système de fichiers racine en lecture seule, capacités supprimées, seccomp RuntimeDefault et aucune élévation
de privilèges.
Transitions restantes connues
Ces fondations ne signifient pas que tous les champs binaires sont déjà des objets. Les enregistrements de voix,
les pièces jointes de chat, les avatars et les futures ressources binaires définies par des extensions nécessitent
des métadonnées de référence explicites, une double lecture et un remplissage, une rétention et des tests de suppression
avant leur migration. De même, chaque futur appelant de plongements doit transmettre le modèle, les dimensions,
la version, la révision source, le propriétaire, la portée de la ressource et les droits fiables au moyen de
VectorStore ; l'accès direct aux tables de vecteurs n'est pas un raccourci accepté.
Les nouveaux effets de bord longs ou visibles à l'extérieur doivent enregistrer une cible de ressource durable, prendre en charge l'annulation et les nouvelles tentatives et utiliser une limite transactionnelle de mise en file ou de boîte d'envoi avec la mutation relationnelle propriétaire. Ajoutez chaque nouvelle ressource aux barrières d'acceptation entre répliques pour le téléversement, la lecture, la recherche et la suppression, ainsi que la sauvegarde et la restauration, avant de l'activer dans les déploiements équipe.