Normaliser et centraliser les types de relations #106
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Normaliser et centraliser les types de relations
Contexte
Les relations enregistrent actuellement leur type sous forme de texte libre dans relations.type_relation.
Cette liberté produit rapidement plusieurs valeurs différentes pour un même concept :
email et Email ;
Réseaux sociaux et Réseaux Sociaux ;
Envoie fausses places et Envoie des fausses places.
Le champ mélange également deux notions différentes :
le type canonique, réutilisable et exploitable par les filtres, le graphe et les outils OSINT ;
le libellé particulier décrivant ce qui s’est produit dans une relation précise.
Par exemple, « envoie des fausses places » décrit davantage le fait observé qu’un type de relation générique.
Problème
Les variantes typographiques ou rédactionnelles provoquent :
des filtres et regroupements incohérents ;
des doublons sémantiques dans le graphe ;
une détection de doublon insuffisante lorsque seul le texte exact est comparé ;
des libellés difficiles à réutiliser dans les traitements automatiques ;
une dégradation progressive de la qualité des données ;
une migration future plus risquée si le problème continue à s’étendre.
Une simple conversion en minuscules ne suffit pas. Elle corrigerait certaines variantes de casse, mais pas les espaces multiples, les variantes Unicode ni les formulations proches.
Objectif
Introduire un référentiel persistant de types de relations et faire référencer chaque relation vers un type canonique.
Le type doit devenir une donnée structurée. Le champ label reste libre et sert à préciser le fait particulier représenté par la relation.
Le système doit :
fusionner automatiquement uniquement les variantes strictement équivalentes après normalisation technique ;
ne jamais fusionner automatiquement deux formulations seulement supposées équivalentes ;
permettre à l’utilisateur de renommer et fusionner explicitement des types ;
empêcher la création future de variantes équivalentes ;
préserver intégralement les relations, preuves, positions du graphe et provenances OSINT existantes.
Modèle de données attendu
Ajouter un référentiel types_relation, en suivant autant que possible les conventions déjà utilisées pour les autres référentiels du projet.
Chaque type doit posséder au minimum :
un identifiant persistant ;
un code métier stable lorsqu’il s’agit d’un type fourni par l’application ;
un libellé canonique affichable ;
une clé normalisée utilisée pour l’unicité ;
une description facultative ;
une indication permettant de distinguer les types système des types personnalisés.
La clé normalisée doit être produite par une fonction métier unique et testée. Elle doit au minimum :
supprimer les espaces en début et fin ;
réduire les suites d’espaces à un espace ;
normaliser la représentation Unicode ;
appliquer une comparaison Unicode insensible à la casse.
Les relations ne doivent plus utiliser le texte libre comme identité du type. Elles doivent référencer l’identifiant du type canonique par une clé étrangère avec suppression interdite lorsqu’il est encore utilisé.
Le champ libre label de la relation est conservé pour décrire le cas particulier.
Types fournis par l’application
Prévoir un petit ensemble initial de types génériques réellement réutilisables, sans imposer une taxonomie exhaustive.
Les codes utilisés automatiquement par les fonctionnalités existantes doivent rester stables, notamment les relations produites par les traitements OSINT et DNS.
Les libellés affichés peuvent être traduits ou améliorés ultérieurement sans modifier les codes métier persistés.
Les types personnalisés restent autorisés, mais leur clé normalisée doit être unique.
Migration des bases existantes
La migration doit être transactionnelle et conservatrice.
Pour chaque valeur historique de relations.type_relation :
nettoyer et normaliser la valeur ;
créer ou réutiliser un type canonique possédant la même clé normalisée ;
rattacher la relation à ce type ;
conserver comme libellé canonique la première forme rencontrée selon un ordre déterministe ;
préserver les identifiants, dates, statuts, niveaux de confiance, labels et justifications des relations.
Ainsi :
email et Email doivent devenir un seul type ;
Réseaux sociaux et Réseaux Sociaux doivent devenir un seul type ;
Envoie fausses places et Envoie des fausses places ne doivent pas être fusionnés automatiquement, car cette équivalence est sémantique et non strictement technique.
Ces deux dernières valeurs pourront ensuite être fusionnées explicitement par l’utilisateur vers un type plus générique, par exemple un type signifiant « envoie » ou « transmet », tandis que le détail « fausses places » restera dans le libellé ou la justification.
La migration doit également :
reconstruire proprement les contraintes, index et déclencheurs nécessaires ;
préserver les tables de liaison vers les preuves, la chronologie et les exécutions OSINT ;
préserver les positions et l’affichage du graphe ;
exécuter PRAGMA foreign_key_check avant validation ;
ne mettre à jour la version du schéma qu’après réussite complète ;
effectuer un rollback intégral à la moindre erreur.
La version actuelle du schéma doit être déterminée depuis le dépôt au moment de l’implémentation, puis incrémentée selon les conventions existantes.
Gestion des types dans l’interface
Dans les interfaces de création et de modification d’une relation :
remplacer la saisie libre du type par un sélecteur de types canoniques ;
permettre de rechercher un type par son libellé ;
permettre la création explicite d’un type personnalisé ;
refuser un nouveau type lorsque sa clé normalisée existe déjà ;
afficher clairement la différence entre « Type de relation » et « Libellé de la relation ».
Ajouter une interface minimale de gestion des types permettant :
de consulter les types et le nombre de relations associées ;
de renommer le libellé canonique ;
de fusionner un type source dans un type cible ;
de confirmer explicitement une fusion ;
de rafraîchir immédiatement la barre latérale, les détails et le graphe après modification.
Une fusion doit être entièrement transactionnelle.
Si la fusion créerait deux relations ayant la même source, la même cible et le même type canonique, l’opération doit être bloquée avec une erreur claire. Aucune relation, preuve ou justification ne doit être supprimée automatiquement pour résoudre ce conflit.
Un type système peut voir son libellé d’affichage modifié seulement si l’architecture le permet sans casser son code stable. Son code métier ne doit jamais être modifiable depuis l’interface.
Couche métier et persistance
Créer les modèles, DAO et services nécessaires en respectant la séparation actuelle des responsabilités :
aucun accès SQLite direct depuis les widgets ;
aucune dépendance GTK dans les modèles, DAO ou services métier ;
gestion explicite de la durée de vie des allocations ;
erreurs structurées remontées jusqu’à l’interface ;
transactions gérées dans la couche appropriée.
La détection des doublons de relations doit désormais utiliser l’identifiant du type canonique et non son libellé affiché.
Tous les producteurs de relations existants doivent être adaptés :
création manuelle ;
modification depuis la fiche d’une relation ;
intégration de résultats OSINT ;
relations DNS ;
chargement du graphe ;
historique et provenance OSINT ;
tests et fixtures.
Critères d’acceptation
Une table ou structure persistante dédiée centralise les types de relations.
Chaque relation référence un type canonique par clé étrangère.
Le texte libre historique n’est plus utilisé comme identité du type.
La normalisation est implémentée dans une fonction métier unique et testée.
email et Email sont regroupés automatiquement lors de la migration.
Réseaux sociaux et Réseaux Sociaux sont regroupés automatiquement lors de la migration.
Deux formulations seulement proches ne sont jamais fusionnées automatiquement.
L’utilisateur peut fusionner explicitement deux types.
Une fusion conflictuelle est refusée sans modification partielle.
La création d’une variante équivalente après normalisation est refusée.
Le type est choisi depuis un sélecteur dans la création et l’édition d’une relation.
Le champ label reste disponible pour le détail propre à la relation.
Les types générés par les outils OSINT conservent un code métier stable.
Les anciennes bases sont migrées sans perte de relations ni de liaisons.
Les bases neuves utilisent directement le nouveau schéma.
Le graphe et la barre latérale affichent le libellé canonique après migration ou fusion.
La suite complète de tests passe sans avertissement de compilation.
Tests attendus
Ajouter au minimum des tests pour :
la normalisation de la casse, des espaces et de l’Unicode ;
l’unicité de la clé normalisée ;
la création, la lecture, la modification et le comptage des types ;
le refus de suppression d’un type utilisé ;
la migration d’une base contenant les exemples du ticket ;
la conservation des identifiants et métadonnées des relations ;
la conservation des liaisons vers les preuves et les exécutions OSINT ;
la création et la modification d’une relation avec un type canonique ;
la détection d’un doublon par identifiant de type ;
la fusion réussie de deux types ;
le rollback d’une fusion provoquant un conflit ;
le chargement du graphe avec les libellés canoniques ;
les codes de types utilisés par les intégrations OSINT existantes.
Hors périmètre
création d’une taxonomie OSINT exhaustive ;
traduction complète des types ;
fusion automatique fondée sur une distance de Levenshtein ou une analyse sémantique ;
suppression automatique d’une relation pour résoudre un conflit ;
modification des preuves originales.
Définition de terminé
Le ticket est terminé lorsque :
le schéma neuf et la migration sont fonctionnels ;
les données historiques sont préservées ;
les variantes strictement équivalentes sont regroupées ;
les variantes sémantiques peuvent être fusionnées manuellement ;
toutes les interfaces de relation utilisent le référentiel ;
tous les producteurs de relations utilisent des codes stables ;
make clean, la compilation, la suite complète de tests et git diff --check réussissent ;
aucun commit n’est créé tant que la fonctionnalité n’est pas entièrement validée.