Production2026

Leganews Pro

Une plateforme de recherche et de veille sur les textes juridiques congolais

Illustration de Leganews Pro

Leganews est né en 2019 d’un problème concret. En République démocratique du Congo, les professionnels du droit consultent souvent les publications officielles, les sites institutionnels, les fichiers numérisés, les archives privées et les documents transmis par leurs collègues avant de trouver le texte recherché.

J’ai cofondé le produit et travaillé à la fois sur son orientation et sur son logiciel. Il a fallu écouter les professionnels du droit et les éditeurs, maintenir la première application en production et décider quelles parties de son modèle ne pouvaient plus porter la version suivante.

Leganews est passé d’une base de données juridique à une plateforme de veille juridique fondée sur un corpus éditorialisé, une recherche structurée, des textes juridiques versionnés, une validation éditoriale, des relations juridiques, des alertes, la comparaison de documents, des droits d’accès et la facturation.

Il ne s’agit pas d’une réécriture nette. Le premier produit a confirmé le besoin de recherche, d’abonnements, de paiements, de favoris, d’historique et d’outils éditoriaux. Il a aussi montré qu’un modèle de contenu trop générique et des responsabilités couplées compliquaient chaque ajout. La plateforme actuelle traduit ces leçons dans un modèle juridique plus précis.

L’objectif n’est pas de remplacer les publications officielles ni le jugement d’un professionnel du droit. Il est de réduire le temps et l’incertitude entre une question juridique et les sources nécessaires pour la traiter de façon responsable.

Une règle guide le produit :

Un texte juridique devient réellement utile lorsqu’il peut être trouvé, vérifié, lu dans la bonne version, relié aux textes associés et suivi au fil de ses évolutions.

Le problème

Leganews traite l’incertitude créée lorsque l’information juridique est répartie entre de nombreuses sources.

En République démocratique du Congo, un avocat, une entreprise, un chercheur, un magistrat ou un étudiant peut devoir consulter tour à tour le Journal officiel, des sites institutionnels, des moteurs de recherche, des collections de PDF, des archives physiques et des documents reçus de collègues avant de trouver un texte utile.

Même après avoir trouvé un document, plusieurs questions demeurent :

  • S’agit-il du bon texte juridique ?
  • Le titre, le numéro, la date et la source sont-ils exacts ?
  • Est-ce la version originale ou une version ultérieure ?
  • Le texte a-t-il été modifié, complété, remplacé ou abrogé ?
  • Le document est-il complet ?
  • Existe-t-il une décision connexe ou un texte d’application ?
  • Comment le retrouver lorsque je reviendrai sur le même dossier ?
  • Comment saurai-je qu’un élément pertinent a changé ?

Un dossier de PDF résout le stockage, mais pas la recherche juridique. Une recherche générique sur un site peut trouver des mots-clés, mais elle ne comprend ni les types de textes, ni les juridictions, ni les classifications, ni les matières, ni les versions, ni les relations. Une base de données simple peut répertorier des enregistrements, mais elle ne fournit pas automatiquement un processus éditorial permettant de décider ce qui devient public.

En pratique, la recherche juridique devient un travail de reconstruction répété. Chaque professionnel crée son propre système de favoris, de dossiers, de noms de fichiers, de notes et de repères mémorisés. Ce système est difficile à vérifier, à partager et à maintenir.

Leganews remplace ce parcours fragmenté par les étapes suivantes :

Mermaid

Le corpus est volontairement présenté comme éditorialisé plutôt qu’exhaustif. La présence d’un texte dans Leganews ne prouve pas, à elle seule, qu’il est actuellement en vigueur. La plateforme aide les utilisateurs à examiner les sources, les dates, les versions et les relations, mais l’analyse juridique finale reste une responsabilité professionnelle.

Orientation du produit

Leganews est parti d’une idée produit simple :

Construire une base de données numérique structurée des textes juridiques congolais.

Cette idée était utile, mais insuffisante.

Une plateforme juridique professionnelle devait faire davantage que téléverser et afficher des documents. Elle devait :

  • modéliser les actes normatifs et la jurisprudence sans les réduire à des fichiers génériques ;
  • préserver l’identité stable d’un texte juridique tout en prenant en charge plusieurs versions ;
  • structurer les textes longs en articles, sections, chapitres, paragraphes et annexes ;
  • séparer le travail éditorial en brouillon de la publication publique ;
  • relier les textes par des relations porteuses de sens juridique ;
  • proposer une recherche en texte intégral avec des filtres juridiques ;
  • permettre aux utilisateurs d’enregistrer des textes dans des dossiers contextualisés et d’y joindre des notes personnelles ;
  • suivre des domaines, des matières et des textes précis ;
  • avertir les utilisateurs lorsqu’une version correspondante est publiée ;
  • comparer deux versions ou des documents téléversés ;
  • gérer les accès individuels et ceux des organisations ;
  • traiter de manière sûre les moyens de paiement locaux ;
  • migrer des années de données historiques sans perdre leur sens métier ;
  • rester observable et testable à mesure que le produit évolue.

Le produit est ainsi passé d’un site de contenu à un système d’information juridique.

L’application publique constitue l’espace de recherche et de veille. L’application d’administration constitue l’espace éditorial et opérationnel. L’API Symfony porte les règles métier, tandis que PostgreSQL, Redis, le stockage d’objets et Mercure prennent en charge la recherche, les traitements en arrière-plan, les fichiers et les mises à jour en temps réel.

De la plateforme historique à Leganews 2.0

La première plateforme Leganews n’était pas un prototype jetable. C’était une application Symfony en production qui suivait déjà le Domain-Driven Design, traitait les abonnements et les transactions FlexPay, gérait les utilisateurs, publiait du contenu juridique, enregistrait les favoris et l’historique de recherche, générait des PDF et proposait des interfaces publiques et administratives.

Sa stack reflétait le produit à ce stade :

Plain text
Symfony + Twig
Stimulus + Turbo + Symfony UX Live Components
Webpack Encore
MariaDB / MySQL
Doctrine ORM and Doctrine Messenger
Cron-driven maintenance jobs

La première application regroupait le code dans ContentManagement, IdentityAndAccess, SubscriptionBilling, Marketing et un SharedKernel. Ce modèle nous a permis de livrer, mais ses concepts sont devenus trop larges pour la version suivante.

L’entité historique Content en est un bon exemple. Un seul objet contenait le titre, le Markdown, le HTML, l’extrait, la catégorie, la sous-catégorie, la date de publication, l’état de mise en ligne, l’indicateur d’accès public, la source, le type, l’état juridique, la référence, le nombre de favoris, le nombre de vues et le nombre de vues uniques.

Ce modèle convenait à la publication d’un enregistrement courant comparable à un article. Il est devenu limitant lorsqu’il a fallu représenter un objet juridique stable comprenant plusieurs versions, des articles et chapitres structurés, des transitions éditoriales, une consolidation, des citations, des pièces jointes, des manifestations générées et différentes règles d’accès.

La même pression est apparue ailleurs :

  • Favorite ne pouvait relier qu’un utilisateur à un contenu, alors que la recherche juridique exigeait des dossiers nommés, des éléments enregistrés, des notes et du contexte.
  • SubscriptionBilling portait à la fois le comportement commercial du paiement et l’accès créé par un achat, ce qui rendait les règles de paiement et de droits plus difficiles à faire évoluer indépendamment.
  • IdentityAndAccess réunissait l’identité du compte et les préoccupations d’accès liées aux organisations et aux abonnements.
  • des références directes aux objets traversaient les frontières des contextes : charger ou modifier un concept pouvait ainsi faire intervenir le modèle d’un autre contexte dans la même opération ;
  • le site public et l’interface d’administration reposaient sur la même exécution Symfony, Twig et Symfony UX, alors que leurs parcours devenaient très différents ;
  • MariaDB stockait correctement les données du produit, mais les nouvelles exigences de recherche et d’analyse tiraient mieux parti de la recherche en texte intégral, des trigrammes, des données adaptées aux intervalles, de JSONB et d’HyperLogLog proposés par PostgreSQL.

La refonte n’était donc pas une mise à niveau de framework. Elle modifiait notre manière de décrire le métier.

Modèle historiqueModèle actuelRaison du changement
ContentWork, Expression, Expression Unit, ManifestationSéparer l’identité juridique stable, les versions sémantiques, la structure et les rendus
Category et SubCategoryClassification, Subject, Work Type, Work Source, JurisdictionReprésenter explicitement les différentes dimensions de classification juridique
FavoriteBookmark, Bookmark Item, Work NotePréserver le contexte de la recherche juridique au lieu d’un simple indicateur d’enregistrement
Vues et compteurs de contenusConsultations de Monitoring et projections HLLSéparer l’historique utilisateur des statistiques agrégées de lecture capables de passer à l’échelle
ContentManagementCorpus et MonitoringSéparer la vérité juridique éditoriale des activités de découverte et de suivi des utilisateurs
IdentityAndAccessIdentity et AccessSéparer l’identité de l’utilisateur de ce à quoi celui-ci ou son organisation peut accéder
SubscriptionBillingBilling et AccessSéparer l’argent, les commandes et les événements du prestataire des droits et des sièges
Une application rendue par SymfonyAPI Symfony avec applications TanStack Start principale et d’administrationPermettre aux parcours clients et opérationnels d’évoluer indépendamment
Couplage de session navigateur/serveurBFF de même origine avec jetons Symfony côté serveurGarder les jetons d’accès et de renouvellement hors du stockage du navigateur
MariaDBPostgreSQLPrendre en charge une recherche, des projections, une indexation et des analyses JSONB et HLL plus riches
Entrées cron manuellesSymfony Scheduler et MessengerConserver les planifications dans le code et déplacer les traitements lents vers des files observables

La plateforme échange des identifiants, des commandes, des modèles de lecture et des événements entre les contextes au lieu de partager leurs agrégats. Billing exécute une commande payée sans modifier un abonnement. Monitoring possède les bookmarks et référence les Works par leur identité. Corpus ne possède pas les favoris d’un utilisateur.

La refonte du frontend a suivi le même principe. Au lieu de laisser les templates, les contrôleurs, le comportement des sessions et l’interface produit évoluer ensemble, la plateforme dispose désormais d’une API backend et de deux applications React dédiées. L’application principale porte les parcours publics de découverte et de libre-service. L’application d’administration porte les parcours éditoriaux et opérationnels. Des packages partagés fournissent les contrats d’API, les parcours d’authentification, la recherche, le lecteur juridique, le comportement de l’éditeur, les primitives d’interface, l’analyse et les utilitaires, sans imposer aux deux applications la même architecture d’écran.

Cette refonte nous a aussi permis de remplacer les comportements implicites par des cycles de vie explicites :

Mermaid

Le modèle actuel nomme les distinctions révélées par l’usage en production de la première plateforme.

Architecture du système

Leganews utilise maintenant sept contextes métier :

  1. Corpus porte les Works juridiques, les Expressions, le texte structuré, la validation éditoriale, les pièces jointes et les relations juridiques.
  2. Monitoring porte la recherche, les alertes, les notifications, les bookmarks, les notes, les consultations et les recherches récentes.
  3. Identity porte les utilisateurs, l’authentification, le cycle de vie des comptes, les identités fédérées et les vérifications de sécurité.
  4. Access porte les abonnements, les organisations, les membres, les invitations et les droits d’accès directs aux Works.
  5. Billing porte les produits, les prix, les commandes, les transactions de paiement et les événements des prestataires.
  6. Compare porte les parcours de comparaison de documents et de versions juridiques.
  7. Policy porte les conditions et les documents de confidentialité versionnés de la plateforme.

Le backend suit le Domain-Driven Design et une architecture en couches au sein de chaque contexte délimité :

Mermaid

Les commandes modifient l’état. Les requêtes renvoient des projections conçues pour un usage précis. Doctrine ORM persiste les agrégats, tandis que Doctrine DBAL gère les recherches optimisées, les rapports, les tableaux et les modèles de lecture couvrant plusieurs enregistrements.

Mermaid

La publication, la recherche, les abonnements et les paiements changent pour des raisons différentes. Chaque contexte conserve ses termes et ses règles, puis échange des identifiants ou des événements avec les autres.

Modélisation d’un corpus juridique

La décision la plus difficile en matière de conception concernait ce que la plateforme devait réellement stocker.

Un modèle naïf pourrait utiliser une table nommée documents, avec un titre, un PDF et une date de publication. Cela fonctionne jusqu’à ce que le même acte juridique reçoive une nouvelle version, qu’un éditeur structure son contenu, qu’un texte ultérieur le modifie ou que les utilisateurs aient besoin de comparer deux états du droit.

Leganews distingue plutôt quatre concepts reliés : le Work juridique stable, ses Expressions sémantiques, leurs Expression Units structurelles et les Manifestations techniques utilisées pour la lecture ou le téléchargement.

Cette distinction est centrale dans la plateforme.

Un Work peut être un acte normatif ou une décision de jurisprudence. Il porte des métadonnées stables, telles que son titre, son type, sa source, sa classification, sa matière, sa date de publication, sa référence juridique, sa politique d’accès et son état éditorial courant dérivé.

Une Expression représente une version de ce Work. Les Expressions possèdent un type, un numéro de version, une date d’expression, une période de validité, un état de structuration, un état éditorial et un résumé. Les types d’expression actuels sont "originale" et "consolidée".

Une Expression Unit représente la structure interne de la version : corps, préambule, livre, partie, titre, chapitre, section, article, paragraphe, alinéa, point ou annexe. Les Units forment une hiérarchie au moyen d’identifiants parents et de chemins matérialisés.

Une Manifestation est le rendu technique présenté au lecteur, comme du HTML structuré, du Markdown, du texte brut ou un PDF généré.

Mermaid

Ce modèle permet à la plateforme de conserver une page stable pour l’objet juridique tout en indiquant la version exacte consultée par l’utilisateur. Il fournit aussi une base pour les périodes de validité, la consolidation, les comparaisons, les citations et de futures améliorations de la recherche juridique temporelle.

Parcours éditorial

Une information juridique ne doit pas devenir publique uniquement parce qu’un enregistrement existe dans la base de données.

Leganews utilise une machine à états éditoriaux explicite pour les Expressions :

Mermaid

Les éditeurs peuvent soumettre une Expression structurée à la validation. Les réviseurs peuvent l’approuver ou demander des modifications en ajoutant obligatoirement un commentaire. Le contenu approuvé peut ensuite être publié. Un contenu retiré ou approuvé peut être rouvert comme brouillon.

La publication est un événement métier, pas la mise à jour d’un booléen.

Lorsqu’une Expression est publiée, la plateforme peut :

  • dériver l’état éditorial public du Work ;
  • actualiser le résumé du Work à partir de la dernière Expression publiée ;
  • construire une Manifestation lisible ;
  • projeter les citations juridiques intégrées dans des relations entre Works ;
  • mettre à jour le document de recherche ;
  • générer des comparaisons avec d’autres Expressions publiées ;
  • planifier les notifications correspondant aux alertes des utilisateurs.
Mermaid

L’état public du Work provient de ses Expressions. Une ancienne version publiée reste visible lorsqu’un éditeur crée un nouveau brouillon.

L’application d’administration accompagne ce parcours au moyen d’un éditeur de textes juridiques et de contrôles de validation. L’éditeur stocke une représentation destinée à l’édition, tandis que le backend persiste séparément les Expression Units au niveau du domaine. L’expérience d’édition reste ainsi distincte du modèle structuré canonique utilisé pour la recherche, la lecture, l’exportation et la comparaison.

Relations juridiques

Les textes juridiques ne sont pas des enregistrements indépendants.

Un texte peut en citer, modifier, modifier partiellement, abroger, abroger partiellement, mettre en œuvre, appliquer, ratifier, interpréter, consolider ou remplacer un autre. Traiter ces liens comme de simples hyperliens génériques leur ferait perdre leur sens juridique.

Leganews les modélise sous forme de Work Relations.

Une relation confirmée enregistre un Work source, un Work cible, un type de relation et, éventuellement, un ancrage dans une Expression ou une Expression Unit. Certaines relations modifient aussi l’état du domaine. Par exemple, appliquer une relation d’abrogation à un acte normatif peut faire passer le statut du Work cible à "abrogé". Une relation de modification peut éventuellement initialiser une Expression consolidée à partir du contenu pertinent le plus récent.

Lorsqu’un éditeur publie une Expression, un gestionnaire projette ses références intégrées en relations cites. Les processus automatisés et les règles d’importation enregistrent leurs propositions comme Work Relation Suggestions, avec des éléments probants et un niveau de confiance, pas comme des faits juridiques.

Les suggestions et les relations confirmées suivent des parcours différents :

Mermaid

L’automatisation peut aider à découvrir des liens possibles. Elle ne doit pas être autorisée à publier une signification juridique sans validation.

Recherche et accès à l’information

Une fois le contenu juridique structuré, le défi suivant est de le retrouver.

Leganews ne parcourt pas toutes les tables normalisées à chaque recherche. Un gestionnaire projette les Works publiés dans search_documents, avec la dernière Expression, le titre, les intertitres, le corps, les références juridiques et les métadonnées filtrables.

PostgreSQL fournit le premier moteur de recherche.

La couche de recherche utilise :

  • une configuration française de recherche en texte intégral ;
  • la normalisation unaccent ;
  • des valeurs tsvector pondérées pour les titres, les intertitres et le corps du texte ;
  • des index GIN pour la recherche en texte intégral ;
  • des index trigrammes pour la correspondance approximative de repli ;
  • des résultats classés avec mise en évidence dans le titre et le corps ;
  • des filtres par catégorie de Work, type, source, juridiction, classification, matière, accès et date ;
  • des portées explicites limitées au titre, au corps ou au texte intégral.

La première tentative utilise la recherche en texte intégral de PostgreSQL. Si elle ne renvoie aucun résultat, le moteur se replie sur la similarité par trigrammes. Cela aide à gérer les variations orthographiques, les références incomplètes et les requêtes qui se prêtent mal à la tokenisation.

Mermaid

La recherche se trouve dans le contexte Monitoring plutôt que dans Corpus, car elle s’inscrit dans l’activité de recherche continue de l’utilisateur. Ce même contexte porte les recherches récentes, les suggestions, les Works enregistrés, les notes, les consultations et les alertes.

Le frontend regroupe cette expérience dans un module de recherche réutilisable, partagé entre les interfaces publiques et administratives. Les utilisateurs peuvent commencer par une recherche large, sélectionner une portée, appliquer des filtres juridiques, examiner les fragments mis en évidence et conserver suffisamment de contexte pour vérifier le résultat, plutôt que de considérer une correspondance de mots-clés comme une conclusion juridique.

Veille, alertes et recherche personnelle

Trouver un texte une première fois ne représente qu’une partie du travail juridique. Les professionnels doivent aussi revenir sur un dossier et le suivre dans le temps.

Leganews modélise la veille au moyen de plusieurs fonctionnalités ciblées :

Mermaid

Les bookmarks sont plus utiles qu’une liste de favoris sans structure, car ils préservent le contexte. Un utilisateur peut organiser les Works par client, question de recherche, dossier contentieux ou matière suivie. Les notes personnelles restent attachées au Work afin de ne pas perdre la raison de son enregistrement.

Les alertes peuvent cibler une classification juridique entière, une matière ou un Work précis. Lorsqu’une Expression est publiée, un gestionnaire asynchrone recherche par lots limités les utilisateurs abonnés correspondants. Il déduplique les notifications, applique les politiques d’accès, enregistre une notification non lue, publie un événement Mercure en temps réel et envoie un courriel lorsque ce canal est activé.

La plateforme propose aussi un récapitulatif hebdomadaire de veille aux utilisateurs qui préfèrent recevoir une synthèse regroupée.

Mermaid

La publication devient ainsi une boucle de rétroaction produit. L’équipe éditoriale ajoute ou actualise une source juridique, le système la rend accessible à la recherche, puis les utilisateurs qui suivent le périmètre concerné sont informés sans devoir répéter la même recherche chaque jour.

Comparaison de documents et de versions

Le travail juridique implique souvent de comparer ligne par ligne deux versions d’un document.

Leganews prend en charge deux parcours de comparaison associés :

  1. comparer deux Expressions publiées du même Work ;
  2. comparer deux fichiers PDF ou DOCX privés téléversés par un utilisateur abonné.

Le parcours de documents téléversés accepte deux fichiers d’une taille maximale de 10 Mo chacun. Le traitement s’exécute de manière asynchrone, car l’extraction et la génération du diff ne doivent pas bloquer la requête HTTP.

Pour les fichiers PDF, la plateforme extrait le texte UTF-8 avec pdftotext. Pour les fichiers DOCX, elle lit le document WordprocessingML directement depuis l’archive ZIP et préserve la séparation des paragraphes et des tableaux. Le texte est normalisé avant que l’algorithme unifié diff du système d’exploitation ne produise les ajouts, les suppressions et les blocs de contexte.

L’agrégat de comparaison possède un cycle de vie clair :

Mermaid

Le worker de comparaison supprime les téléversements après le traitement. Une tâche planifiée efface les résultats après sept jours. Mercure et le courriel indiquent à l’utilisateur la réussite ou l’échec.

L’implémentation gère aussi les cas limites opérationnels : sommes de contrôle identiques, texte extrait vide, suivi des modifications dans les fichiers DOCX, diffs trop volumineux, fichiers non pris en charge et motifs d’échec sûrs qui n’exposent aucun détail interne.

Accès et facturation

L’accès au contenu juridique constitue un domaine distinct du paiement.

Un paiement enregistre un événement commercial. Access décide quel contenu ou quelle fonction l’acheteur peut utiliser.

Leganews prend en charge deux modes d’accès :

Mermaid

Lorsqu’un utilisateur demande un Work protégé, le mécanisme d’autorisation vérifie d’abord l’existence d’un droit direct actif. À défaut, il évalue l’accès par abonnement, y compris la couverture de l’organisation et les rôles privilégiés.

Billing porte les produits, les prix, les commandes, les lignes de commande, les transactions de paiement et les événements des prestataires. Access porte les abonnements, les organisations, les adhésions, les invitations, les sièges et les droits sur les Works. Les deux contextes collaborent au moyen de services d’exécution et d’événements explicites.

Le parcours de paiement répond aux besoins locaux au moyen de FlexPay, notamment pour les paiements par mobile money et par carte en CDF ou en USD.

Mermaid

Les callbacks suivent un traitement idempotent. Le gestionnaire calcule une empreinte pour chaque événement, ignore les répétitions, verrouille la transaction et empêche une seconde exécution. Il valide chaque ligne avant de créer les droits et ne marque la commande comme exécutée qu’après la réussite de tous les éléments.

C’est l’un des cas où la séparation des domaines apporte une sécurité concrète. Billing peut confirmer que l’argent a été encaissé. Access détermine ce que cet achat est autorisé à débloquer.

API et applications web

Leganews dispose de deux applications React construites avec TanStack Start :

Mermaid

Les deux applications utilisent React, TanStack Router, TanStack Query, Tailwind CSS, Zod et des packages d’espace de travail partagés, gérés avec Bun et Turborepo.

Le navigateur ne stocke pas les jetons Symfony. Chaque application TanStack Start les conserve côté serveur et donne au navigateur un cookie de session HTTP-only. Sa route /api ajoute le jeton d’accès, renouvelle si possible une session expirée, transmet la requête à Symfony puis la relance après un renouvellement réussi.

L’API reçoit également un en-tête X-Client-Platform. Symfony utilise les métadonnées des contrôleurs et une protection de plateforme centralisée pour empêcher l’application principale d’appeler les interfaces administratives, ou l’application d’administration d’utiliser par inadvertance une route non prise en charge.

Côté TypeScript, @workspace/api expose des clients propres à chaque plateforme :

Mermaid

Les contrats sont définis avec Zod et les types TypeScript sont inférés à partir de ces schémas. Le package masque la construction brute des URL, les détails HTTP et les utilitaires de requête derrière de petites interfaces orientées produit.

Les requêtes traversent cette frontière :

Mermaid

Le frontend peut se concentrer sur les parcours utilisateur. Symfony reste responsable des décisions métier.

Migration de la plateforme historique

Leganews n’est pas un produit créé de zéro. L’initiative a commencé plusieurs années avant l’architecture actuelle, et la nouvelle plateforme doit préserver les données utiles de l’application précédente.

L’environnement de développement exécute à la fois PostgreSQL et la base MariaDB historique. Un importateur fondé sur des plans déplace les enregistrements dans l’ordre de leurs dépendances :

Mermaid

Chaque plan d’importation associe un concept historique au nouveau modèle de domaine, détecte les conflits, prend en charge les simulations et les filtres, puis indique si chaque ligne a été insérée, ignorée, rejetée ou a échoué.

Les importations s’exécutent par lots limités afin qu’un grand jeu de données historiques n’ait pas à tenir entièrement en mémoire. Le parcours de réinitialisation peut reconstruire la base PostgreSQL, importer les données historiques et d’amorçage, reconstruire les projections de recherche, téléverser de nouveau les pièces jointes dans le stockage d’objets, rapprocher les relations de citation et synchroniser les abonnements expirés.

La migration n’est pas traitée comme une copie SQL ponctuelle. L’ancien schéma et le nouveau modèle de domaine n’expriment pas les mêmes concepts. Une correspondance au moyen de plans explicites rend ces différences visibles et permet aux nouvelles règles du domaine de rester la référence.

L’import préserve les données historiques sans reprendre tout l’ancien modèle dans la nouvelle application.

IA appliquée et frontières éditoriales

Leganews confie délibérément un rôle limité à l’IA.

Lorsqu’une Expression publiée ne possède aucun résumé éditorial, la plateforme peut générer un court résumé en français au moyen d’un modèle OpenAI ou Gemini configuré. Le prompt exige un résumé factuel, sans interprétation ni information absente de la source. La taille de l’entrée est limitée, les défaillances du fournisseur sont journalisées et le résumé conserve sa provenance : manuelle, générée ou extraite.

Si aucun fournisseur n’est configuré ou si la génération échoue, le parcours de publication peut se replier sur un résumé déterministe extrait des Expression Units. La publication ne doit pas devenir indisponible parce qu’un modèle externe l’est.

Le même principe s’applique aux relations juridiques. Les systèmes automatisés peuvent créer des suggestions de relation assorties d’éléments probants et d’un niveau de confiance, mais une suggestion reste distincte d’une relation juridique confirmée.

La règle de conception est la suivante :

L’IA peut accélérer le travail éditorial, mais elle ne doit pas devenir silencieusement la source de la vérité juridique.

Fiabilité, observabilité et tests

Une plateforme qui dépend de tâches en arrière-plan, de paiements, d’un stockage externe, d’une diffusion en temps réel et de parcours éditoriaux ne peut pas se contenter de réponses HTTP réussies.

Leganews utilise Symfony Messenger adossé à Redis pour le travail asynchrone et le stockage des messages en échec. Des tâches planifiées gèrent notamment les abonnements expirés, le nettoyage des comparaisons, les récapitulatifs de veille, le nettoyage des comptes et les rapports mensuels de la plateforme.

Les signaux opérationnels sont séparés selon leur finalité :

  • journaux applicatifs structurés avec rotation ;
  • journaux d’audit métier ;
  • capture des erreurs compatible avec Sentry ;
  • notifications Telegram pour les défaillances métier critiques ;
  • identifiants de corrélation entre les bus et les requêtes ;
  • contrôles d’état pour les tableaux de bord opérationnels ;
  • événements Google Analytics après assainissement des données personnelles dans les applications web.

Les statistiques de consultation des Works utilisent HyperLogLog pour estimer le nombre de lecteurs uniques. Les métriques de lecture agrégées restent ainsi utiles sans conserver une ligne d’historique anonyme détaillée pour chaque visite.

Les tests sont eux aussi répartis par responsabilité :

Mermaid

Les scénarios Behat sont particulièrement utiles, car ils décrivent le comportement de l’application dans le langage du produit : une Expression publiée rend un Work lisible, un webhook de paiement dupliqué n’est traité qu’une fois, un abonné expiré ne reçoit plus d’alerte et une organisation avec un abonnement actif ne peut pas être archivée.

Les tests du domaine consignent les règles de publication, la création des droits et l’exécution idempotente des paiements.

Principales décisions d’ingénierie

Modéliser le sens juridique avant les fichiers

La plateforme ne traite pas un PDF comme l’objet juridique. Work, Expression, Unit et Manifestation séparent l’identité stable, la version sémantique, la structure et le rendu technique.

Ce modèle ouvre la voie au versionnement, à la consolidation, à la recherche, aux citations, à la comparaison et aux futures requêtes temporelles.

Faire de la publication un événement

La publication d’une Expression est le moment où le travail éditorial devient un comportement du produit. L’indexation de recherche, les résumés, les manifestations, les citations, les comparaisons et les alertes réagissent tous à cette transition.

L’éditeur reste ainsi concentré sur le travail éditorial, tandis que les fonctionnalités en aval demeurent découplées.

Séparer les suggestions des faits juridiques

Une suggestion de relation générée par l’IA ou importée n’est pas une Work Relation confirmée. Les éléments probants, le niveau de confiance et la validation éditoriale établissent une frontière explicite entre assistance et autorité.

Utiliser PostgreSQL avant d’ajouter un cluster de recherche distinct

PostgreSQL fournit déjà la recherche française en texte intégral, le classement, la mise en évidence, les trigrammes, les filtres relationnels et les index. Un service de recherche distinct ajouterait des coûts de déploiement et de synchronisation avant que le produit ait démontré les limites de PostgreSQL.

Séparer la facturation de l’accès

La réussite d’un paiement ne signifie pas directement "afficher le contenu". Billing enregistre la vérité commerciale ; Access accorde les droits dans le produit. Une exécution idempotente relie les deux.

Garder les jetons hors du stockage du navigateur

Le BFF TanStack Start porte la session de chaque application, transmet les requêtes de même origine et renouvelle les jetons Symfony côté serveur. Les sessions principale et d’administration restent séparées.

Traiter la migration historique comme une traduction du domaine

L’ancien schéma MariaDB est une source, et non le modèle cible. Des plans d’importation ordonnés traduisent les anciens enregistrements dans le domaine actuel et signalent explicitement les conflits.

Utiliser le traitement asynchrone lorsque l’utilisateur ne doit pas attendre

L’extraction de documents, les comparaisons, les alertes, les courriels et les autres parcours en arrière-plan passent par Messenger. Mercure referme la boucle de rétroaction en actualisant l’interface lorsque le traitement change d’état.

Utiliser l’IA comme un adaptateur remplaçable

La génération de résumés se trouve derrière une interface applicative, prend en charge plusieurs fournisseurs, conserve la provenance et dispose d’une solution de repli déterministe. Le cœur du corpus ne dépend pas d’un fournisseur d’IA unique.

Ce que j’ai appris

Le principal enseignement de Leganews est que téléverser des fichiers ne résout pas l’accès au droit. Le système doit préserver la source du texte, sa version, sa structure, les textes qu’il modifie et les éléments qui permettent d’évaluer son usage.

Mon rôle de cofondateur a changé ma façon d’aborder la refonte. Je ne pouvais pas évaluer le système uniquement comme ingénieur. Chaque changement d’architecture devait protéger des années de travail éditorial, les utilisateurs existants, les règles commerciales et la confiance attachée au nom Leganews. La meilleure conception n’était pas le modèle le plus pur pris isolément, mais celui qui pouvait faire progresser le produit sans faire comme si son histoire n’existait pas.

J’ai également appris que le parcours éditorial fait partie de l’architecture. La recherche publique ne peut pas dépasser la qualité du processus interne de création, de relecture, de correction, d’approbation, de publication et de retrait.

La recherche a pris plus d’importance que prévu. Une fois le corpus structuré, le défi suivant n’était plus le stockage, mais l’accès à l’information : normalisation du français, classement, correspondance approximative de repli, filtres, mise en évidence et métadonnées suffisantes pour permettre aux utilisateurs d’évaluer un résultat.

La veille a aussi modifié l’orientation du produit. Une recherche juridique se limite rarement à une seule requête. Les bookmarks, les notes, les recherches récentes, les alertes, les notifications en temps réel et les récapitulatifs hebdomadaires permettent de reprendre un dossier dans le temps.

La migration depuis la plateforme historique a renforcé un autre enseignement : une réécriture doit préserver l’histoire métier sans conserver toutes les anciennes abstractions. Des plans d’importation explicites ont permis de traduire des années de données dans un modèle de domaine plus clair, tout en consignant ce qui ne pouvait pas être associé en toute sécurité.

Les paiements m’ont appris l’importance de l’idempotence. Les prestataires relancent les callbacks, les utilisateurs répètent des actions et les parcours distribués peuvent échouer entre deux étapes. Des empreintes d’événement stables, des verrous d’enregistrement, une validation préalable et une exécution idempotente rendent le parcours commercial fiable.

L’IA n’est utile ici que si son autorité reste limitée. Les résumés générés et les suggestions de relation peuvent réduire le travail éditorial, mais la plateforme en conserve la provenance et impose une validation humaine.

Travail en cours

Leganews Pro relie désormais le corpus juridique, la validation éditoriale, la recherche indexée, la veille, la comparaison de documents, la facturation et les accès des organisations. La migration doit aussi protéger les années de contenu et d’historique commercial de la première application.

Mon travail actuel porte moins sur des fonctionnalités isolées que sur la solidité de ces frontières. Un paiement doit ouvrir le bon accès. Une version publiée doit mettre à jour la recherche et les alertes. Une relation importée doit rester une suggestion tant qu’un éditeur ne l’a pas confirmée.

Le but n’a pas changé depuis 2019 : raccourcir le chemin entre une question juridique et les sources nécessaires pour y répondre.

Autres projets

Tout voir

2025

Basango

Un pipeline peu coûteux pour collecter et classer l’actualité des médias congolais

Voir

2025

PHP Packages Graph

Cartographier les dépendances et la maintenance des paquets Packagist

Voir

2025

Points of Interest

Une carte de chaleur mise à jour par des signalements anonymes à proximité

Voir