27 KiB
Architecture
EvidencePreviewWidget est l’adaptateur GTK unique de EvidencePreview pour
CreatePersonDialog et la fiche directe. Il encapsule les états, le rendu
EML/PDF/image/texte/vidéo, l’annulation, la génération, la garde de session et
l’arrêt du média. Les deux écrans lui transmettent uniquement une source
interne ou de staging accompagnée du SHA-256 attendu.
Aperçu contrôlé multi-format
EvidencePreview vérifie l’empreinte du fichier interne ou de staging,
détecte son contenu et produit un résultat borné sans GTK. BackgroundTask
travaille hors du thread principal ; CreatePersonDialog y crée ensuite
textures, buffers et médias, rejette les générations périmées et arrête tout
média au changement ou à la fermeture. L’aperçu ne persiste rien.
Le mode aperçu de EmlMimeExtractor réutilise le parcours récursif et les
décodages RFC 2047/2231 sans écrire les pièces jointes. Il préfère
text/plain, transforme un éventuel HTML en texte inerte et retourne
l’inventaire possédé. Le contrôleur vidéo indépendant de GTK orchestre
pause, retour au début, détachement et libération via des actions injectées.
Version : 3.1 Dernière mise à jour : 2026-07-28 Schéma SQLite courant : V14
Personnes contextuelles — SQLite V14
person_role_assignments sépare les rôles contextuels des champs de l’entité.
Une personne peut porter plusieurs rôles avec preuve facultative, provenance,
confiance et notes. Les anciens codes sont copiés littéralement depuis
person_roles avec la provenance legacy_manual. Le service crée l’entité,
les rôles et le rattachement manuel dans une transaction unique.
Le cœur EvidencePreview vérifie l’intégrité avant décodage PNG/JPEG, applique
des bornes et ne renvoie qu’un PNG mémoire réduit. Une BackgroundTask
travaille hors du thread GTK ; la texture est créée sur le contexte principal.
Le dialogue annule l’ancienne tâche et rejette les générations obsolètes.
L’interface conserve une génération de session et les chemins stables du
projet et de sa base. PDF, vidéo, EML avancé et OCR restent exclus.
OCR contrôlé d’identité — SQLite V15
La V15 sépare l’exécution OCR, l’observation du document et les observations de champs. Le moteur reçoit uniquement une copie contrôlée ou une page PDF explicitement choisie, conserve texte brut, TSV, paramètres, langues, version, SHA-256, confiance et coordonnées, puis laisse la révision à l’utilisateur. Les widgets n’accèdent pas à SQLite : le coordinateur persiste les décisions acceptées ou modifiées dans la transaction finale et compense les fichiers en cas d’échec.
La provenance visuelle est rendue par OcrProvenanceOverlay. La conversion
des coordonnées source vers la zone affichée est indépendante de GTK et tient
compte du ratio, de la réduction, de l’agrandissement et des marges. Le
rectangle est transitoire : aucune annotation n’est écrite dans la preuve.
Les langues proposées proviennent exclusivement de tesseract --list-langs.
Le DAO V15 expose des lectures possédées pour les exécutions, observations de
documents et observations de champs, ainsi que des listes ordonnées par preuve,
personne ou observation documentaire.
Statut : architecture courante
1. Objectif
Ce document décrit l'architecture logicielle actuelle de Labfy Investigation.
Il définit :
- les responsabilités des couches ;
- la direction autorisée des dépendances ;
- le cycle de vie d'une enquête ;
- la place de SQLite et du système de fichiers ;
- le fonctionnement des tâches asynchrones ;
- l'intégration des outils externes ;
- la projection graphique des données ;
- les règles de sécurité et de traçabilité.
La documentation détaillée du schéma SQLite se trouve dans :
docs/database/DATABASE_ARCHITECTURE.md
docs/database/SCHEMA_AUDIT_CURRENT.md
2. Vision
Labfy Investigation est un poste de travail local d'investigation numérique et d'OSINT développé en C17 avec GTK4.
Une enquête doit pouvoir être :
- créée ;
- ouverte ;
- copiée ;
- sauvegardée ;
- archivée ;
- transmise ;
avec son dossier et sa base SQLite.
Le logiciel n'est pas encore prêt pour un usage opérationnel en production. Les formats et interfaces peuvent évoluer tant que le projet reste en développement actif.
3. Sources de vérité
Pour déterminer l'état réel d'une fonction :
- code de
main; - tests ;
- migrations SQL ;
- commits ;
- tickets Forgejo ;
- documentation.
Les documents historiques ne décrivent pas l'état courant.
SQLite est la source de vérité des données structurées d'une enquête.
Le système de fichiers est la source de vérité des fichiers originaux et dérivés référencés par la base.
Le graphe, la barre latérale et les autres vues ne possèdent pas leur propre copie métier indépendante.
4. Principes fondamentaux
4.1 Une enquête est autonome
MonEnquete/
├── 00_BaseDeDonnees/
│ └── Enquete.sqlite
├── 01_Preuves_Originales/
├── 02_Preuves_Traitees/
├── 03_Chronologie/
├── 04_Entites/
└── 05_Rapports/
Aucune donnée métier d'une enquête ne doit être stockée dans une base globale.
Les préférences générales de l'application, lorsqu'elles seront ajoutées, resteront séparées des données d'enquête.
4.2 Les preuves originales sont immuables
L'application ne modifie jamais un fichier original importé.
Toute annotation, conversion, extraction, analyse ou expurgation produit un objet dérivé.
4.3 Le cœur ne dépend pas de GTK
Les modèles, DAO et services métier doivent pouvoir être testés sans lancer l'interface graphique.
4.4 Les widgets ne contiennent pas la logique métier
Un widget :
- affiche un état ;
- collecte une intention utilisateur ;
- déclenche une action de l'application ;
- présente le résultat.
Il ne :
- construit pas de requête SQL ;
- ne déplace pas directement une preuve ;
- ne lance pas une commande shell ;
- ne décide pas seul de la validation métier d'une donnée.
4.5 Les traitements longs sont asynchrones
Le thread GTK principal ne réalise pas les opérations longues.
4.6 Les résultats automatiques restent révisables
Une donnée OCR, OSINT ou dérivée ne devient pas un fait confirmé sans action explicite lorsque le domaine l'exige.
5. Architecture en couches
┌──────────────────────────────────────────────┐
│ Interface GTK4 │
│ views / widgets │
└──────────────────────┬───────────────────────┘
│ intentions et affichage
┌──────────────────────▼───────────────────────┐
│ Application et contrôleurs │
│ cycle de vie, session, navigation, messages │
└──────────────────────┬───────────────────────┘
│ orchestration
┌──────────────────────▼───────────────────────┐
│ Services métier et tâches │
│ import, relations, OSINT, EML, graphe │
└───────────────┬───────────────────┬──────────┘
│ │
┌───────────────▼────────────┐ ┌────▼─────────────────┐
│ DAO │ │ Adaptateurs │
│ requêtes métier SQLite │ │ fichiers / CLI / API│
└───────────────┬────────────┘ └────┬─────────────────┘
│ │
┌───────────────▼───────────────────▼──────────┐
│ Infrastructure │
│ SQLite / transactions / système de fichiers │
└──────────────────────────────────────────────┘
Les modèles métier circulent entre ces couches sans dépendre de GTK ni de SQLite.
6. Organisation du dépôt
database/ scripts SQL versionnés et schéma courant
docs/ architecture, conventions et procédures
include/core/ interfaces des services et du cœur
include/dao/ interfaces d'accès métier aux données
include/database/ interfaces de l'infrastructure SQLite
include/models/ modèles métier
include/views/ fenêtres et dialogues GTK
include/widgets/ widgets réutilisables
resources/ ressources de l'application
src/core/ services, tâches et orchestration métier
src/dao/ requêtes métier SQLite
src/database/ connexion, schéma, statements, transactions, erreurs
src/models/ implémentation des modèles
src/views/ fenêtres et dialogues GTK
src/widgets/ composants GTK réutilisables
tests/ tests unitaires et d'intégration ciblée
7. Responsabilités des modules
7.1 Point d'entrée et application
src/main.c démarre l'application.
La couche application :
- gère le cycle de vie GTK ;
- crée la fenêtre principale ;
- ouvre ou crée une enquête ;
- remplace la session active uniquement après succès ;
- coordonne les messages utilisateur ;
- relie les services métier aux vues ;
- ferme proprement les ressources.
Une erreur d'ouverture ne doit pas détruire une session valide déjà active.
7.2 Core et services métier
src/core contient notamment :
- représentation et validation d'une enquête ;
- session et projet d'enquête ;
- construction de l'arborescence ;
- tâches d'arrière-plan ;
- gestionnaire de tâches ;
- registre et catalogue d'outils ;
- exécution de processus ;
- hachage et copie de fichiers ;
- import et intégrité des preuves ;
- services d'entités et de relations ;
- chargement du graphe ;
- actions OSINT ;
- analyse EML, IBAN, OCR, métadonnées et PDF ;
- vocabulaire contrôlé ;
- pipeline EML.
Un service métier peut coordonner plusieurs DAO, une transaction et une opération de fichier.
7.3 Modèles
src/models représente les données manipulées par l'application.
Les modèles :
- ne lancent pas de requête SQL ;
- ne dépendent pas de GTK ;
- valident leurs invariants lorsque cela leur appartient ;
- exposent une API claire de création, lecture et destruction.
7.4 Infrastructure Database
src/database gère :
- ouverture et fermeture de SQLite ;
- activation des clés étrangères ;
- lecture de la version ;
- installation du schéma ;
- migrations ;
- statements préparés ;
- transactions ;
- traduction structurée des erreurs.
Cette couche ne contient pas l'orchestration complète d'une fonctionnalité utilisateur.
7.5 DAO
src/dao contient les requêtes métier.
Un DAO :
- transforme des lignes SQLite en modèles ;
- utilise des statements préparés ;
- ne dépend pas de GTK ;
- ne lance pas d'outil externe ;
- ne décide pas seul d'un workflow multi-étapes ;
- expose des erreurs exploitables par le service appelant.
7.6 Vues et widgets
src/views contient les fenêtres et dialogues complets.
src/widgets contient les composants réutilisables, notamment :
- barre latérale ;
- arborescence ;
- panneau de tâches ;
- listes ;
- espace de travail ;
- graphe.
Les vues et widgets ne deviennent pas propriétaires des données persistées.
8. Cycle de vie d'une enquête
8.1 Création
sélection du dossier
↓
validation du chemin
↓
création de l'arborescence
↓
initialisation transactionnelle de SQLite V14
↓
création de l'identité de l'enquête
↓
ouverture d'une session
↓
construction des vues
Un échec laisse l'application dans un état cohérent et nettoie les artefacts partiels prévus par le service.
8.2 Ouverture
sélection du dossier
↓
validation de l'arborescence
↓
ouverture de SQLite
↓
lecture de schema_version
↓
migration éventuelle
↓
chargement de l'enquête
↓
construction de l'arborescence et du graphe
↓
remplacement atomique de la session active
Une base plus récente que l'application doit être refusée.
8.3 Fermeture
La fermeture libère :
- les tâches ;
- les références de modèles ;
- la connexion SQLite ;
- la session ;
- les widgets dépendants ;
- les ressources externes.
9. Gestion des preuves
9.1 Import
Le flux d'import vise à garantir l'intégrité :
validation de la source
↓
SHA-256 source
↓
copie vers une destination contrôlée
↓
SHA-256 destination
↓
écriture SQLite
↓
validation ou nettoyage
L'import groupé traite les fichiers de manière contrôlée et produit un bilan détaillé.
9.2 Reclassement
Un changement de type peut impliquer :
- vérification préalable de l'intégrité ;
- déplacement cohérent du fichier interne ;
- mise à jour SQLite ;
- rollback et restauration en cas d'échec.
L'UUID, l'empreinte et l'historique ne doivent pas être recréés silencieusement.
9.3 Dérivés
Les extractions, OCR, pièces jointes EML et versions traitées restent reliés à leur preuve source.
10. Tâches asynchrones
10.1 Création d’une personne avec preuves
PersonEvidenceSelection possède la collection ordonnée des preuves retenues
et distingue les preuves existantes des copies de staging. Il ne dépend ni de
GTK ni de SQLite. EvidenceStaging refuse les fichiers spéciaux et liens
symboliques, calcule l’empreinte de la source et de sa copie, détecte le MIME
et nettoie les temporaires lors d’un retrait ou d’une annulation.
PersonCreationCoordinator valide toutes les empreintes avant écriture, crée
la personne, importe les nouvelles preuves et rattache toute la collection
dans une transaction SQLite. Les copies définitives réalisées avant un échec
sont supprimées après rollback. PersonCreationTask exécute cette orchestration
hors du thread GTK. Un changement de session annule les tâches et interdit le
rafraîchissement d’une autre enquête.
Les aperçus PNG/JPEG utilisent exclusivement le fichier interne d’une preuve existante ou sa copie de staging. PDF, vidéo, EML et autres formats ne sont pas analysés dans cette tranche.
Les tâches longues utilisent l'infrastructure de tâche d'arrière-plan et le gestionnaire de tâches.
Une tâche expose selon ses besoins :
pending
running
completed
failed
cancelled
Elle doit :
- éviter l'accès direct à GTK depuis un thread de travail ;
- transférer le résultat vers le thread principal ;
- conserver une erreur structurée ;
- libérer ses ressources même après annulation ;
- ne pas laisser une transaction ouverte ;
- ne pas écrire simultanément dans SQLite sans coordination.
11. Outils externes et OSINT
11.1 Registre et catalogue
Le registre détecte la présence et la version des outils.
Le catalogue décrit les capacités et les actions compatibles avec une sélection.
Une dépendance absente désactive l'action concernée sans empêcher le démarrage.
11.2 Exécution
Les outils sont lancés avec GSubprocess.
Les arguments sont transmis séparément.
Aucune commande shell dynamique n'est construite.
Les exécutions persistées peuvent conserver :
- outil et version ;
- cible et paramètres ;
- dates ;
- code de retour ;
- sorties brutes ;
- empreintes ;
- statut d'analyse ;
- objets intégrés.
11.3 Intégration
Une action OSINT suit le modèle :
sélection
↓
validation de l'action
↓
tâche asynchrone
↓
sortie brute
↓
propositions normalisées
↓
révision
↓
intégration transactionnelle
↓
rafraîchissement des vues
12. Graphe d'enquête
Le graphe est une projection de SQLite.
Il représente notamment :
- entités ;
- relations ;
- preuves ou extractions lorsque le modèle le prévoit ;
- positions et viewport persistés séparément des données métier.
Les coordonnées et le zoom sont un état de présentation.
Une modification du graphe qui change le métier doit passer par un service et être persistée dans SQLite avant d'être considérée comme acquise.
Le graphe ne doit jamais inventer une relation seulement parce que deux nœuds sont proches visuellement.
13. Pivot EML
13.1 Parcours
preuve EML
↓ contrôle d'intégrité SHA-256
tâche asynchrone
↓
analyse des en-têtes
↓
extraction MIME récursive vers un staging
↓
outils documentaires optionnels
↓
propositions temporaires
↓ confirmation explicite
observations persistantes dans la fiche
↓ promotion facultative
entités canoniques du graphe
La preuve originale n'est jamais modifiée. Le staging et ses pièces jointes extraites sont supprimés après rejet, annulation, erreur ou intégration. L'absence d'ExifTool, Tesseract ou Poppler conserve un résultat partiel : l'analyse des en-têtes et MIME reste utilisable.
13.2 Responsabilités
EmlAnalyzerlit les en-têtes, conserve leurs occurrences et qualifie les adresses, domaines et IP.EmlMimeExtractorparcourt les parties imbriquées, y comprismessage/rfc822, décode Base64, quoted-printable, RFC 2047 et RFC 2231, assainit les noms et applique les limites de profondeur, nombre et taille.EmlPipelineTaskorchestre en arrière-plan l'analyse, le staging, les outils documentaires et les propositions bancaires.DocumentToolRunnerlance les programmes avecGSubprocess, sans shell, draine simultanémentstdoutetstderr, borne les sorties et propage l'annulation.- les modules ExifTool, OCR et PDF structurent les résultats sans modifier la source. Le PDF privilégie le texte natif puis utilise l'OCR page par page.
BankProposalconserve les valeurs bancaires détectées, leur normalisation, leur validation et une éventuelle correction OCR distincte.EmlAnalysisDialogprésente les résultats et collecte séparément la conservation et la promotion.EmlIntegration, les DAO etEvidenceObservationassurent l'écriture transactionnelle, la déduplication, la promotion et le retrait.Application,MainWindowetWorkspaceraccordent la tâche au contexte GTK principal, rafraîchissent le graphe et rechargent la fiche depuis SQLite.
13.3 Proposition, observation et entité
Une proposition est un résultat temporaire. Elle peut être rejetée, invalidée, corrigée, conservée ou accompagnée d'une demande de promotion.
Une observation est une information confirmée liée à une preuve. La table
evidence_entity_observations conserve son UUID, son type, ses valeurs brute,
normalisée et corrigée éventuelle, son rôle, l'en-tête et son occurrence, sa
provenance, son statut, ses dates et une association facultative à une entité.
Une observation peut donc exister durablement sans nœud de graphe.
Une entité est un objet canonique réutilisable de entites. Elle n'est
créée ou réutilisée que si « Promouvoir en entité » est explicitement coché.
preuve_entites fournit alors le rattachement nécessaire à la projection du
graphe. Une même entité peut servir plusieurs rôles, observations, preuves ou
relations.
13.4 MIME et outils documentaires
L'extracteur accepte un EML de 50 Mio au maximum. Il limite une partie décodée
à 8 Mio, le total décodé à 32 Mio, le message à 128 parties, la profondeur à
12 niveaux et un nom produit à 240 octets. Les chemins MIME sont conservés,
les fichiers inline et Content-ID sont inventoriés, les traversées de chemin
sont neutralisées et les écritures passent par un temporaire renommé après
succès. Cette prise en charge volontairement bornée ne prétend pas couvrir
l'intégralité des RFC MIME.
Une analyse documentaire accepte au maximum 50 Mio, 8 Mio de stdout,
256 Kio de stderr, 100 pages PDF et 128 documents par pipeline. Un PDF
chiffré n'est pas contourné. pdfinfo inspecte le document, pdftotext
fournit en priorité le texte natif et pdftoppm rend les pages nécessitant un
OCR. L'ordre des pages, les résultats partiels et la méthode utilisée sont
conservés ; les images temporaires sont nettoyées.
Tesseract reçoit fra+eng dans le pipeline. Son texte brut n'est pas corrigé
silencieusement : une correction OCR proposée reste distincte. Les arguments,
la version et l'état de l'exécution documentent la provenance.
ExifTool est appelé en sortie JSON avec les groupes de tags. Les champs connus sont normalisés et les tags inconnus sont conservés avec leur groupe, leur nom et leur valeur brute. La version de l'outil est attachée à l'exécution. Les coordonnées GPS sont marquées sensibles et ne créent jamais automatiquement une entité.
Les propositions bancaires peuvent contenir IBAN brut et normalisé, validation MOD-97, BIC, banque, titulaire déclaré, adresse, éléments de RIB et correction OCR distincte. Une donnée invalide n'est pas intégrable. Un titulaire déclaré dans un document n'établit ni identité certaine ni attribution pénale : la donnée reste une proposition puis une observation tant que l'enquêteur ne choisit pas de la promouvoir.
13.5 Migrations V11, V12 et V13
V11 crée le premier modèle evidence_entity_observations, où chaque
observation est obligatoirement liée à une entité.
V12 donne un UUID propre à l'observation, rend entity_id nullable, ajoute les
valeurs corrigées, l'extraction, les avertissements, les dates d'observation,
d'intégration et de promotion ainsi que promotion_kind. Les lignes V11 sont
reprises avec promotion_kind = 'legacy'. L'index sémantique assure la
déduplication, y compris lorsque extraction_id est nul.
V13 ajoute preuve_entite_sources. Chaque rattachement matérialisé possède
une justification manual, legacy_manual ou eml_observation. La migration
protège les lignes historiques par legacy_manual et reprend les promotions
V12 identifiables.
13.6 Promotion et retrait
La conservation seule écrit l'observation et l'affiche dans la fiche, sans
créer entites ni preuve_entites. La promotion explicite crée ou réutilise
une entité, l'associe à l'observation et ajoute le rattachement nécessaire.
L'opération est transactionnelle et idempotente.
« Retirer du graphe » efface uniquement la source eml_observation portant
l'UUID de l'observation et conserve
l'observation. Le nœud n'est supprimé que si les références connues
(observations, preuves, relations, tags, recherches, chronologie, hypothèses,
OSINT, comptes sociaux et rôles de personne) sont absentes.
13.7 Qualification et provenance
Les rôles couvrent From, Sender, Reply-To, Return-Path, To, Cc,
Bcc, les relais Received et le domaine de Message-ID. Une même adresse
peut conserver plusieurs rôles sans multiplier l'entité canonique.
192.0.2.10 et 198.51.100.20 sont des IP, jamais des domaines ;
MIME-Version: 1.0 ne produit pas de domaine intégrable.
13.8 Asynchronisme et sécurité
BackgroundTask, TaskManager et GCancellable portent l'état, la
progression, l'annulation et la remise du résultat au contexte principal.
Le worker ne manipule aucun widget. Avant de présenter le résultat,
Application vérifie que la session attendue est toujours active ; un
changement d'enquête rend le résultat caduc et déclenche le nettoyage.
Tous les arguments externes sont séparés, sans shell. stdout et stderr
sont drainés en parallèle pour éviter un interblocage. Les processus sont
forcés à terminer lors d'une annulation, puis les répertoires temporaires sont
supprimés.
13.9 Limites connues
- la promotion est disponible dans le dialogue d'analyse, pas directement depuis la fiche ;
- la fiche affiche la valeur canonique et les codes persistés, mais pas encore la valeur brute distincte ni l'UUID de l'entité associée ;
- le runner borne les sorties et gère l'annulation, mais ne possède pas de délai maximal autonome ;
- les pièces jointes analysées dans le staging ne sont pas persistées comme dérivés confirmés par ce parcours ;
- les rattachements antérieurs à V13 restent volontairement protégés par
legacy_manual, faute de provenance historique plus précise ; - la couverture visuelle du dialogue et de la fiche reste manuelle.
14. Erreurs et journalisation
Les couches basses produisent des erreurs structurées.
Les services ajoutent le contexte métier.
L'application décide :
- du journal technique ;
- du message utilisateur ;
- du maintien ou du remplacement de la session ;
- de la possibilité de réessayer.
Les messages ne doivent pas divulguer inutilement :
- chemins absolus sensibles ;
- données personnelles ;
- contenu complet d'une preuve ;
- secrets ou jetons.
15. Sécurité
Règles obligatoires :
- requêtes préparées pour les données variables ;
- clés étrangères activées ;
- chemins contrôlés ;
- neutralisation des traversées
../; - aucune ouverture automatique de pièce jointe ;
- aucun chargement automatique de ressource distante d'un e-mail ;
- limites de taille et de profondeur pour les formats complexes ;
- aucune commande shell dynamique ;
- aucune installation automatique d'outil ;
- aucune donnée réelle d'enquête dans les tests ou le dépôt ;
- aucune action intrusive non autorisée.
16. Tests
Le cœur, les modèles, DAO, migrations et tâches possèdent des tests ciblés.
Les tests GTK restent limités aux composants qui nécessitent réellement GTK.
Les scénarios critiques incluent :
- base neuve ;
- migration ;
- rollback ;
- import interrompu ;
- annulation ;
- erreur d'outil ;
- donnée malformée ;
- doublon ;
- intégrité ;
- clés étrangères ;
- conservation de la valeur brute ;
- absence d'une dépendance optionnelle.
Validation :
make clean
make -j8
make -j8 test
git diff --check
17. Règles d'évolution
Une nouvelle fonctionnalité doit :
- respecter la direction des dépendances ;
- réutiliser les services existants avant d'en créer un concurrent ;
- définir clairement la propriété mémoire ;
- ajouter les tests nécessaires ;
- documenter les formats persistés ;
- utiliser des fixtures synthétiques ;
- préserver les données brutes ;
- maintenir la branche compilable ;
- mettre à jour l'architecture lorsque ses responsabilités changent.