diff --git a/CHANGELOG.md b/CHANGELOG.md index f97a1e2..7042983 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ ## [0.1.0-dev] — en préparation, non publiée +### Interface Web finale locale + +- Web devient l’interface utilisateur `CURRENT` unique : coque Catppuccin + Mocha/Lavender Agent | Graphe | Activité, drawer transversal et cartes + SPECIMEN pour conversation, plan, hypothèse, autorisation et résultat. +- Retrait du client, des vues, widgets, tests, headers et dépendance de build + GTK4 ; les services C, SQLite V20, fondation financière V21, capabilities et + JobStore V4 sont conservés. +- Ajout de `tools/labfy` : instance loopback vérifiée, navigateur ouvert et + session HttpOnly/SameSite automatique sans code ni jeton dans l’URL ; les + mutations restent protégées par Host, Origin exact et CSRF. + ### Connexion Web - La session de `3600` secondes (une heure) commence à l'authentification, et non au démarrage @@ -146,6 +158,21 @@ - Finalisation JobStore V3 : budgets opposables au claim, temps monotone, réserve conservée après crash, états de plan exportés et scénario Firefox J8. +# Changements locaux non publiés — recherche OSINT assistée V1 + +- JobStore V4 additif à V3 : persistance atomique et idempotente des plans, + actions, grants, campagnes, résultats et reçus de recherche, sans évolution + de V20 ni de la tranche financière V21. +- Policy explicite de sélection, exclusions, révocation, expiration, identité + d'enquête/plan/action et budgets ; aucune propagation implicite par seed, + CNAME, redirection ou nouvelle URL. +- Transport commun indisponible sans backend lié et libcurl couvert seulement + par fixtures/loopback ; aucun fournisseur public n'est configuré ou qualifié. +- Adapters normalisateurs DNS, RDAP, CDX, Brave, SearXNG et page, avec résultats + bornés, provenance C et absence de suivi implicite de liens, scripts ou pièces jointes. +- Parcours Web synthétique de préparation, approbation/refus, deux vagues et + révocation durable, avec isolation vérifiée entre espaces de travail A/B. + # Changements locaux non publiés — J9 ## Espace local et import navigateur (non publié) diff --git a/Makefile b/Makefile index b4f02d1..5adec25 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC = gcc PKG_CONFIG = pkg-config -REQUIRED_PACKAGES = gtk4 sqlite3 libheif poppler-glib json-glib-1.0 +REQUIRED_PACKAGES = glib-2.0 gio-2.0 sqlite3 libheif poppler-glib json-glib-1.0 ifeq ($(shell $(PKG_CONFIG) --exists $(REQUIRED_PACKAGES) && echo yes),) $(error Dépendances de compilation manquantes : $(REQUIRED_PACKAGES). Voir docs/DEPENDENCE.md) endif @@ -11,13 +11,9 @@ endif SOURCE_SIZE_LIMIT := 2000 # Exceptions historiques : plafonds constatés avant la tranche V18. SOURCE_SIZE_EXCEPTIONS := \ - src/core/application.c:9325 \ - src/widgets/investigation_graph_view.c:4901 \ - src/widgets/workspace.c:4071 \ - src/views/main_window.c:2239 \ - src/views/create_relation_dialog.c:2043 + src/core/local_job_store.c:2000 -.PHONY: check-source-size web web-start web-status web-stop web-code web-workspace web-workspace-j7 web-workspace-j8 web-workspace-j9 web-workspace-local web-workspace-review-check web-workspace-web-check +.PHONY: check-source-size check-research-libcurl web web-start web-status web-stop web-workspace web-workspace-j7 web-workspace-j8 web-workspace-j9 web-workspace-local web-workspace-review-check web-workspace-web-check .NOTPARALLEL: web-workspace-review-check # CONTRACT: le poste Web possède sa bibliothèque explicite, séparée des @@ -27,10 +23,10 @@ PORT ?= 8081 LIBRARY ?= $(shell python3 -c 'import os; from pathlib import Path; print(Path(os.environ.get("XDG_DATA_HOME", Path.home() / ".local" / "share")) / "labfy-investigation" / "web-8081-lab")') web: tools/local-jobs - tools/labfy-web serve --port "$(PORT)" --library "$(LIBRARY)" + LABFY_LIBRARY="$(LIBRARY)" tools/labfy web-start: tools/local-jobs - tools/labfy-web start --port "$(PORT)" --library "$(LIBRARY)" + tools/labfy-web start --automatic-session --open-browser --port "$(PORT)" --library "$(LIBRARY)" web-status: tools/labfy-web status @@ -38,14 +34,12 @@ web-status: web-stop: tools/labfy-web stop -web-code: - tools/labfy-web code - check-source-size: @limit=$(SOURCE_SIZE_LIMIT); failed=0; \ files="$$(git ls-files --cached --others --exclude-standard -- \ 'src/*.c' 'src/**/*.c' | sort -u)"; \ for file in $$files; do \ + [ -f "$$file" ] || continue; \ lines=$$(wc -l < "$$file"); allowed=$$limit; historical=0; \ for exception in $(SOURCE_SIZE_EXCEPTIONS); do \ case "$$exception" in "$$file":*) \ @@ -61,6 +55,14 @@ check-source-size: done; \ exit $$failed +# CONTRACT: le diagnostic libcurl est limité aux cibles qui compilent le +# transport HTTP concret ; les tests de policy/adapters restent indépendants. +check-research-libcurl: + @$(PKG_CONFIG) --exists libcurl || { \ + echo "Dépendance de compilation manquante : libcurl (requis par le transport HTTP de recherche)." >&2; \ + exit 2; \ + } + web-workspace: tools/local-jobs @test -n "$(WORKSPACE)" || (echo "Usage: make web-workspace WORKSPACE=/tmp/labfy-local-workspace"; exit 2) python3 prototypes/web-graph/run_web_workspace.py --workspace "$(WORKSPACE)" @@ -111,9 +113,9 @@ CFLAGS = -std=c17 \ -Iinclude \ -MMD \ -MP \ - $(shell $(PKG_CONFIG) --cflags gtk4 sqlite3 libheif poppler-glib json-glib-1.0) + $(shell $(PKG_CONFIG) --cflags glib-2.0 gio-2.0 sqlite3 libheif poppler-glib json-glib-1.0) -LDFLAGS = $(shell $(PKG_CONFIG) --libs gtk4 sqlite3 libheif poppler-glib json-glib-1.0) -ljpeg +LDFLAGS = $(shell $(PKG_CONFIG) --libs glib-2.0 gio-2.0 sqlite3 libheif poppler-glib json-glib-1.0) -ljpeg TEST_CFLAGS = -std=c17 \ -Wall \ @@ -130,16 +132,6 @@ EVIDENCE_TYPE_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic ENTITY_TYPE_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic EVIDENCE_TYPE_DAO_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic GRAPH_NODE_POSITION_DAO_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic -EVIDENCE_IMPORT_DIALOG_TEST_CFLAGS := \ - -std=c17 \ - -Wall \ - -Wextra \ - -Werror \ - -Iinclude \ - $(shell $(PKG_CONFIG) --cflags gtk4) - -EVIDENCE_IMPORT_DIALOG_TEST_LDFLAGS := $(shell $(PKG_CONFIG) --libs gtk4) - EVIDENCE_INTEGRITY_VERIFIER_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic ENTITY_RECORD_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic ENTITY_TYPE_DAO_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic @@ -285,6 +277,31 @@ EML_GRAPH_DEMO := tools/eml_graph_demo LOCAL_TOOLKIT_DEMO := tools/local_toolkit_demo LOCAL_JOBS := tools/local-jobs LOCAL_JOBS_TEST := tools/local-jobs-test +TEST_RESEARCH_STORE := tests/test_research_store +TEST_RESEARCH_POLICY := tests/test_research_policy +TEST_RESEARCH_TRANSPORT := tests/test_research_transport +TEST_RESEARCH_ADAPTERS := tests/test_research_adapters + +# CONTRACT: seul le transport HTTP concret lie libcurl ; les contrats et +# adapters restent utilisables dans les tests et outils sans backend réseau. +RESEARCH_SOURCES := \ + src/core/research_contracts.c \ + src/core/research_policy.c \ + src/core/research_transport.c \ + src/core/research_http_transport_curl.c \ + src/core/research_adapter_dns.c \ + src/core/research_adapter_rdap.c \ + src/core/research_adapter_cdx.c \ + src/core/research_adapter_search.c \ + src/core/research_adapter_page.c +RESEARCH_CURL_CFLAGS := $(shell $(PKG_CONFIG) --cflags libcurl) +RESEARCH_CURL_LDFLAGS := $(shell $(PKG_CONFIG) --libs libcurl) +RESEARCH_CURL_TARGETS := $(TARGET) $(TEST_EVIDENCE_METADATA_DIALOG_GTK) \ + $(TEST_EVIDENCE_IDENTITY_IMPORT_GTK) $(TEST_WORKSPACE_IDENTITY_OCR_GTK) + +$(RESEARCH_CURL_TARGETS): check-research-libcurl +$(RESEARCH_CURL_TARGETS): CFLAGS += $(RESEARCH_CURL_CFLAGS) +$(RESEARCH_CURL_TARGETS): LDFLAGS += $(RESEARCH_CURL_LDFLAGS) LOCAL_REVIEW_PREVIEW_SOURCES := \ src/core/observation_review_service.c \ @@ -362,6 +379,28 @@ $(TEST_LOCAL_CAPABILITY_REGISTRY): tests/test_local_capability_registry.c \ $(TEST_LOCAL_JOB_STORE): tests/test_local_job_store.c src/core/local_job_store.c $(CC) $(CORE_GRAPH_CFLAGS) -DLOCAL_JOB_STORE_ENABLE_TEST_HOOKS $^ -o $@ $(CORE_GRAPH_LDFLAGS) +$(TEST_RESEARCH_STORE): tests/test_research_store.c \ + src/core/local_job_store.c src/core/research_contracts.c + $(CC) $(CORE_GRAPH_CFLAGS) $^ -o $@ $(CORE_GRAPH_LDFLAGS) + +$(TEST_RESEARCH_POLICY): tests/test_research_policy.c \ + src/core/research_contracts.c src/core/research_policy.c + $(CC) $(TEST_CFLAGS) -Wpedantic $^ -o $@ $(TEST_LDFLAGS) + +$(TEST_RESEARCH_TRANSPORT): check-research-libcurl \ + tests/test_research_transport.c src/core/research_contracts.c \ + src/core/research_policy.c src/core/research_transport.c \ + src/core/research_http_transport_curl.c + $(CC) $(TEST_CFLAGS) -Wpedantic -DRESEARCH_TRANSPORT_ENABLE_TEST_HOOKS \ + $(RESEARCH_CURL_CFLAGS) $(filter %.c,$^) -o $@ $(TEST_LDFLAGS) \ + $(RESEARCH_CURL_LDFLAGS) + +$(TEST_RESEARCH_ADAPTERS): tests/test_research_adapters.c \ + src/core/research_contracts.c src/core/research_adapter_dns.c \ + src/core/research_adapter_rdap.c src/core/research_adapter_cdx.c \ + src/core/research_adapter_search.c src/core/research_adapter_page.c + $(CC) $(TEST_CFLAGS) -Wpedantic $^ -o $@ $(TEST_LDFLAGS) + $(TEST_LOCAL_CORRELATION): tests/test_local_correlation.c \ src/core/local_correlation_service.c \ src/dao/evidence_dao.c src/dao/evidence_entity_dao.c \ @@ -387,13 +426,17 @@ $(TEST_OBSERVATION_REVIEW_SERVICE): tests/test_observation_review_service.c \ $(LOCAL_JOBS): tools/local_jobs.c src/core/local_job_store.c \ src/core/local_planner_service.c \ - $(LOCAL_REVIEW_PREVIEW_SOURCES) $(LOCAL_TOOLKIT_SOURCES) - $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) + $(LOCAL_REVIEW_PREVIEW_SOURCES) $(LOCAL_TOOLKIT_SOURCES) $(RESEARCH_SOURCES) \ + check-research-libcurl + $(CC) $(CFLAGS) $(RESEARCH_CURL_CFLAGS) $(filter %.c,$^) -o $@ $(LDFLAGS) \ + $(RESEARCH_CURL_LDFLAGS) $(LOCAL_JOBS_TEST): tools/local_jobs.c src/core/local_job_store.c \ src/core/local_planner_service.c \ - $(LOCAL_REVIEW_PREVIEW_SOURCES) $(LOCAL_TOOLKIT_SOURCES) - $(CC) $(CFLAGS) -DLOCAL_JOBS_ENABLE_CRASH_HOOK $^ -o $@ $(LDFLAGS) + $(LOCAL_REVIEW_PREVIEW_SOURCES) $(LOCAL_TOOLKIT_SOURCES) $(RESEARCH_SOURCES) \ + check-research-libcurl + $(CC) $(CFLAGS) -DLOCAL_JOBS_ENABLE_CRASH_HOOK $(RESEARCH_CURL_CFLAGS) \ + $(filter %.c,$^) -o $@ $(LDFLAGS) $(RESEARCH_CURL_LDFLAGS) $(TEST_DIALOG_GEOMETRY_GTK): tests/test_dialog_geometry_gtk.c \ src/views/dialog_geometry.c @@ -454,7 +497,10 @@ $(TEST_PERSON_OCR_PROJECTION_EDITOR_GTK): tests/test_person_ocr_projection_edito src/models/identity_traceability.c $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) -all: $(TARGET) +# CONTRACT: le produit utilisateur est le poste Web local. La cible principale +# construit le bridge C qui conserve les services, SQLite et le JobStore V4, +# sans lier un renderer de bureau historique. +all: $(LOCAL_JOBS) .PHONY: core-graph-demo eml-graph-demo local-toolkit-demo core-graph-demo: $(CORE_GRAPH_DEMO) @@ -1399,7 +1445,7 @@ $(TEST_INVESTIGATION_GRAPH_LOAD_TASK): \ $(CC) $(INVESTIGATION_GRAPH_LOAD_TASK_TEST_CFLAGS) $^ -o $@ \ $(TEST_LDFLAGS) -lsqlite3 -test: \ +test-gtk-legacy: \ $(TEST_NODE) \ $(TEST_TREE_MODEL) \ $(TEST_TREE_BUILDER) \ @@ -1494,6 +1540,10 @@ test: \ $(TEST_LOCAL_TOOL_RUNNER) \ $(TEST_LOCAL_CAPABILITY_REGISTRY) \ $(TEST_LOCAL_JOB_STORE) \ + $(TEST_RESEARCH_STORE) \ + $(TEST_RESEARCH_POLICY) \ + $(TEST_RESEARCH_TRANSPORT) \ + $(TEST_RESEARCH_ADAPTERS) \ $(TEST_LOCAL_CORRELATION) \ $(TEST_LOCAL_PLANNER) \ $(TEST_LOCAL_REPORT) \ @@ -1609,6 +1659,10 @@ test: \ @$(TEST_LOCAL_TOOL_RUNNER) @$(TEST_LOCAL_CAPABILITY_REGISTRY) @$(TEST_LOCAL_JOB_STORE) + @$(TEST_RESEARCH_STORE) + @$(TEST_RESEARCH_POLICY) + @$(TEST_RESEARCH_TRANSPORT) + @$(TEST_RESEARCH_ADAPTERS) @$(TEST_LOCAL_CORRELATION) @$(TEST_LOCAL_REPORT) @$(TEST_OBSERVATION_REVIEW_SERVICE) @@ -1632,6 +1686,24 @@ test: \ %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ +# CONTRACT: la suite canonique valide les services restant dans le produit +# Web-only. Les anciennes assertions de widgets GTK sont retirées avec leur +# renderer, sans retirer les tests C de persistance, graphes, jobs et policy. +test: $(TEST_LOCAL_JOB_STORE) $(TEST_RESEARCH_STORE) $(TEST_RESEARCH_POLICY) \ + $(TEST_RESEARCH_TRANSPORT) $(TEST_RESEARCH_ADAPTERS) \ + $(TEST_SCHEMA_V21) $(TEST_FINANCIAL_DAO) $(TEST_FINANCIAL_FOUNDATION) \ + $(TEST_CORE_GRAPH) $(LOCAL_JOBS_TEST) + @./$(TEST_LOCAL_JOB_STORE) + @./$(TEST_RESEARCH_STORE) + @./$(TEST_RESEARCH_POLICY) + @./$(TEST_RESEARCH_TRANSPORT) + @./$(TEST_RESEARCH_ADAPTERS) + @./$(TEST_SCHEMA_V21) + @./$(TEST_FINANCIAL_DAO) + @./$(TEST_FINANCIAL_FOUNDATION) + @./$(TEST_CORE_GRAPH) + @echo "Tous les tests Web-only C sont valides." + run: $(TARGET) ./$(TARGET) diff --git a/README.md b/README.md index 3a40a9d..47caca2 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,11 @@ Le parcours `CURRENT` de jobs locaux persistants et de reprise J5 est documenté dans [docs/architecture/LOCAL_JOBS_RECOVERY.md](docs/architecture/LOCAL_JOBS_RECOVERY.md). +La [recherche OSINT assistée V1](docs/architecture/OSINT_ASSISTED_RESEARCH.md) +ajoute au JobStore V4 des plans, grants et reçus de policy distincts, validés +uniquement avec des fixtures et un fournisseur loopback `SPECIMEN`. Aucun +fournisseur public n'est configuré ou qualifié ; V20 et V21 ne sont pas modifiés. + Le premier poste Web local pilotable J6 est documenté dans [docs/architecture/WEB_WORKSPACE_CONTROL.md](docs/architecture/WEB_WORKSPACE_CONTROL.md). @@ -67,14 +72,14 @@ données. Labfy vise à relier leurs résultats dans une enquête cohérente : La cible de développement est **v0.1.0**. Le projet reste en développement actif et n'est pas prêt pour un usage opérationnel en production. -**Interface GTK conservée ; poste Web local contrôlé disponible.** La fondation -v0.1.0 reste en développement : le poste Web réutilise le moteur de jobs -persistant existant et une bibliothèque locale explicitement choisie, sans -constituer une interface de production ni une autonomie générale. +**Web est l’interface utilisateur CURRENT ; GTK est supprimé.** La fondation +v0.1.0 reste en développement : le poste local réutilise le moteur de jobs +persistant, la bibliothèque explicitement choisie et les capabilities C, sans +constituer une autonomie générale ni un service distant. ### Disponible aujourd'hui -L'application actuelle est une application de bureau GTK4 en C17. Elle fournit +Le produit actuel est un poste Web local-first devant le cœur C17. Il fournit notamment : - création et ouverture d'enquêtes autonomes avec SQLite versionné ; @@ -207,10 +212,11 @@ effectuées par des adapters, sous contrôle des politiques applicables. ## Interface et expérience cible -GTK demeure temporairement l'interface fonctionnelle existante. La future -interface principale sera Web, avec le graphe comme espace de travail central. -Le protocole local, le mécanisme d'événements et le framework frontend ne sont -pas encore sélectionnés. +Le Web est l’interface fonctionnelle unique, avec le graphe comme espace de +travail central. Sa coque organise **Agent | Graphe | Activité**, complétée par +un drawer transversal de détails, provenance, timeline, recherches, +observations, finance, rapports et tâches. Qwen local, tool calling et le +governor AMD/RAM/swap restent `TARGET`. La cible comprend : @@ -278,7 +284,7 @@ Les dépendances et procédures Arch Linux et Ubuntu sont décrites dans ```bash make -j8 make test -make run +tools/labfy ``` La démonstration cœur/Web synthétique se lance séparément : @@ -293,21 +299,23 @@ python3 run_core_demo.py --port 8765 # ou : python3 run_local_toolkit_demo.py --port 8765 ``` -Le projet exige C17, GTK4, GLib/GIO, SQLite, libheif et Poppler GLib. Plusieurs +outils d'analyse sont optionnels et ne sont jamais installés automatiquement. +Le projet exige C17, GLib/GIO, SQLite, libheif et Poppler GLib. GTK4 n’est plus +une dépendance de compilation. Plusieurs outils d'analyse sont optionnels et +ne sont jamais installés automatiquement. outils d'analyse sont optionnels et ne sont jamais installés automatiquement. Le poste Web local se lance depuis une bibliothèque explicitement désignée ; il écoute par défaut sur `127.0.0.1:8081` : ```bash -make web PORT=8081 LIBRARY=/chemin/vers/la-bibliotheque-locale +LABFY_LIBRARY=/chemin/vers/la-bibliotheque-locale tools/labfy ``` -Les commandes `start`, `status`, `stop` et `code` de ce lanceur, ainsi que les -contrats de stockage local et de session, sont décrits dans -[le contrôle du poste Web](docs/architecture/WEB_WORKSPACE_CONTROL.md). Le -code éphémère affiché au démarrage reste privé : il ne doit ni être ajouté à une -commande, ni enregistré dans la documentation. +Le lanceur rejoint ou démarre une instance locale possédée, ouvre le navigateur +et établit une session HttpOnly sans code manuel ni jeton dans l’URL. Les +contrats de stockage local et de session sont décrits dans +[le contrôle du poste Web](docs/architecture/WEB_WORKSPACE_CONTROL.md). ## Documentation @@ -318,7 +326,9 @@ commande, ni enregistré dans la documentation. - [Décisions architecturales](docs/architecture/decisions/0001-web-local-first.md) - [Toolkit et statuts d'intégration](docs/osint/TOOLKIT.md) - [Toolkit local et runner borné J4](docs/architecture/LOCAL_TOOLKIT_RUNNER.md) +- [Recherche OSINT assistée V1 en laboratoire](docs/architecture/OSINT_ASSISTED_RESEARCH.md) - [Design system cible](docs/ui/DESIGN_SYSTEM.md) +- [Matrice de parité Web / GTK](docs/ui/WEB_GTK_PARITY.md) - [Sécurité, scope et secrets](docs/security/SECURITY_MODEL.md) - [Roadmap canonique](docs/ROADMAP.md) - [Backlog préparé](docs/BACKLOG.md) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index aaa67e8..e08220a 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -8,10 +8,19 @@ Le contrôle navigateur local sur espace exclusivement synthétique est décrit dans [WEB_WORKSPACE_CONTROL.md](architecture/WEB_WORKSPACE_CONTROL.md). Cette surface mutationnelle J6 est distincte des démonstrations read-only J2–J5. +La [recherche OSINT assistée V1](architecture/OSINT_ASSISTED_RESEARCH.md) est +`CURRENT` dans le worktree uniquement pour son parcours de laboratoire : le +JobStore V4 est additif à V3, les grants sont explicites et aucun fournisseur +public n'est configuré ou qualifié. Elle ne modifie ni V20 ni V21. + > **Statut :** direction canonique v0.1.0 -> **Dernière mise à jour :** 2026-09-25 +> **Dernière mise à jour :** 2026-09-27 > **Portée :** architecture actuelle et cible Labfy V2 +> **Interface CURRENT :** le Web local est l'unique interface utilisateur ; +> GTK et ses tests/widgets de renderer sont retirés. Le cœur C17, SQLite, les +> services, capabilities et JobStore V4 n'en dépendent pas. + ## 1. Objet et niveaux de maturité Labfy Investigation est un environnement local-first d'investigation numérique @@ -123,11 +132,11 @@ une hypothèse. Il ne devient pas silencieusement une identité confirmée. ## 3. Architecture actuelle — CURRENT -L'application existante est principalement écrite en C17 avec GTK4, GLib/GIO +Le produit actuel est principalement écrit en C17 avec GLib/GIO et SQLite. ```text -GTK views/widgets +Web frontend local │ intentions et affichage Application / services / tasks │ orchestration @@ -154,7 +163,7 @@ Le socle comprend déjà : - enquêtes autonomes et base versionnée ; - preuves, extractions, entités et relations ; -- graphe interactif GTK et positions persistantes ; +- graphe Web interactif et positions persistantes ; - tâches asynchrones en mémoire ; - registre initial d'outils ; - premiers parcours DNS et documentaires ; @@ -208,7 +217,7 @@ pas une réécriture générale du cœur fonctionnel. SQLite ``` -La future interface principale est Web. GTK reste l'interface fonctionnelle +L'interface principale actuelle est Web. GTK est supprimé ; temporaire et ne sera pas supprimé avant qu'un remplacement validé couvre les parcours nécessaires. @@ -599,7 +608,7 @@ Le parcours local est limité à une instance loopback et à des validations sur fixtures `SPECIMEN`. Son lanceur peut ouvrir une bibliothèque locale explicitement choisie, en créer les enquêtes par le bridge C et n'en active qu'une seule dans une instance. Il ne rouvre pas implicitement l'enquête d'une -session précédente. Cette surface ne change pas son statut : GTK reste le +session précédente. Cette surface ne change pas son statut : le Web reste le parcours fonctionnel actuel et le serveur, son packaging ainsi que le choix du renderer de production restent `UNDECIDED`. @@ -647,3 +656,25 @@ signaux exploratoires ; ils ne prouvent ni identité ni relation métier. Le durcissement P01–P06 couvre le cycle de vie des imports, les réservations, le rejeu, les états terminaux et le framing HTTP du corps. Il ne transforme pas le protocole local en service distant ni en garantie de production. + +## 18. Recherche OSINT assistée V1 — CURRENT de laboratoire + +Le JobStore V4 conserve le worker mono-propriétaire et ajoute des objets +distincts de `local_plan.v1` et de session : plan de recherche, action, +`ScopeGrant`, campagne, résultat et reçu de policy. Les admissions sont +idempotentes et atomiques ; la policy expose les refus d'exclusion, révocation, +expiration, identité d'enquête/plan/action ou budget. Une seed dérivée, une +redirection, un CNAME ou une URL nouvelle ne propage jamais le scope. + +Le transport commun demeure indisponible sans backend lié. La variante libcurl +est validée seulement contre le fournisseur loopback `SPECIMEN` du harness et +rejette les adresses non publiques ; elle ne qualifie aucun fournisseur public +ni configuration de production. Les adapters DNS, RDAP, CDX, Brave, SearXNG et +page normalisent des fixtures bornées ; une `next_piste` demande toujours une +nouvelle préparation et décision humaine. + +Le panneau Web local prépare un plan, permet l'approbation ou le refus explicite +des actions, puis admet une campagne en deux vagues séparées. Les sessions et +CSRF Web restent hors des contrats durables ; les tests synthétiques vérifient +l'isolation des espaces A/B. Le détail canonique, les procédures de harness et +les limites sont dans [OSINT_ASSISTED_RESEARCH.md](architecture/OSINT_ASSISTED_RESEARCH.md). diff --git a/docs/DEPENDENCE.md b/docs/DEPENDENCE.md index 0473a3a..d3762d7 100644 --- a/docs/DEPENDENCE.md +++ b/docs/DEPENDENCE.md @@ -13,7 +13,7 @@ n’est persisté. | Vidéo GTK | `gst-plugins-base`, `gst-plugins-good` | `gstreamer1.0-plugins-base`, `gstreamer1.0-plugins-good` | Les codecs vidéo supplémentaires restent optionnels. -Le Makefile vérifie explicitement GTK4, SQLite, libheif, Poppler GLib et +Le Makefile vérifie explicitement GLib/GIO, SQLite, libheif, Poppler GLib et JSON-GLib avant compilation et renvoie vers ce document si une dépendance manque. @@ -54,6 +54,7 @@ export PATH="$HOME/.local/share/labfy-osint/bin:$PATH" | Résolution réseau | `host` | `sudo pacman -S bind` | `sudo apt install bind9-host` | | WHOIS | `whois` | `sudo pacman -S whois` | `sudo apt install whois` | | Requêtes HTTPS | `curl` | `sudo pacman -S curl` | `sudo apt install curl` | +| Transport HTTP C de recherche (harness V1) | `libcurl` | `sudo pacman -S curl` | `sudo apt install libcurl4-openssl-dev` | | Certificats/TLS | `openssl` | `sudo pacman -S openssl` | `sudo apt install openssl` | | Récupération PDF | `qpdf` | `sudo pacman -S qpdf` | `sudo apt install qpdf` | | Audit de mot de passe PDF | `john`, `pdf2john` | `sudo pacman -S john` | `sudo apt install john` | @@ -138,3 +139,14 @@ données distincte, ni installation automatique. Ses fichiers d'instance et de configuration suivent XDG (`XDG_RUNTIME_DIR`, `XDG_STATE_HOME`) ; la bibliothèque d'enquêtes est une destination locale explicitement fournie par `LIBRARY`, et non une dépendance à installer. + +Le harness de recherche OSINT assistée V1 utilise libcurl pour ses tests de +transport avec un fournisseur loopback `SPECIMEN`. Cette dépendance ne +configure, ne qualifie et ne contacte aucun fournisseur public ; les +fournisseurs externes restent indisponibles tant que leur configuration et +leur autorisation ne sont pas établies par une tranche dédiée. + +GTK4 n’est plus une dépendance de Labfy : le build Web-only exige GLib/GIO, +SQLite, libheif, Poppler GLib, JSON-GLib, Python 3 et Firefox/`puppeteer-core` +pour les validations visuelles. Aucun environnement Wayland, GSK_RENDERER ou +display GTK n’est requis par la suite canonique. diff --git a/docs/README.md b/docs/README.md index 2dc7df2..f2195c2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,7 +1,7 @@ # Documentation de Labfy Investigation > **Version cible :** v0.1.0 Foundation, en préparation et non publiée -> **Interface actuelle :** GTK4 +> **Interface actuelle :** Web local-first ; GTK est retiré du produit. > **Interface cible :** Web local-first ; prototype expérimental J2/J3 présent Cette page sépare l'usage du logiciel actuel, la direction acceptée et les @@ -18,9 +18,11 @@ déjà disponible. - [test manuel du pivot EML](testing/EML_PIVOT_MANUAL_TEST.md). - [poste Web local contrôlé](architecture/WEB_WORKSPACE_CONTROL.md) et [guide du poste Web](ui/WEB_WORKBENCH.md). +- [recherche OSINT assistée V1 en laboratoire](architecture/OSINT_ASSISTED_RESEARCH.md) : + JobStore V4 additif, grants explicites et parcours Web synthétique. -Les guides GTK restent applicables tant que l'interface actuelle est maintenue. -Le poste Web local `CURRENT` ne retire donc aucun parcours GTK ni ne décide le +Les guides GTK archivés décrivent des parcours retirés ; ils ne sont plus des +instructions `CURRENT`. Le poste Web local `CURRENT` remplace le renderer GTK et décide le serveur, le renderer ou le packaging de production. ## Direction v0.1.0 — TARGET diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 2dfafe6..69c5c22 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -34,6 +34,10 @@ construction sans démarrer la refonte fonctionnelle. **Dépendances.** État réel du dépôt et préservation des travaux locaux, dont la tranche financière V21 indépendante. +> **Interface CURRENT local :** la tranche Web finale a remplacé GTK par une +> surface locale Agent | Graphe | Activité + drawer. Le raccord Qwen local, +> tool calling et resource governor AMD/RAM/swap restent `TARGET`. + **Livrables.** README, bannière et source éditable, index documentaire, architecture canonique, contrat du graphe, ADR Web/graph-first/polyglotte, Toolkit, sécurité, design system, roadmap et backlog préparé. diff --git a/docs/architecture/OSINT_ASSISTED_RESEARCH.md b/docs/architecture/OSINT_ASSISTED_RESEARCH.md new file mode 100644 index 0000000..9c9c6cc --- /dev/null +++ b/docs/architecture/OSINT_ASSISTED_RESEARCH.md @@ -0,0 +1,163 @@ +# Recherche OSINT assistée V1 — contrat de laboratoire + +> **Statut :** `CURRENT` dans le worktree, validation exclusivement synthétique +> **Portée :** persistance V4, décisions de scope et parcours Web local de +> recherche assistée ; pas une qualification de fournisseur public + +## 1. Limites de ce qui est livré + +La recherche assistée V1 ajoute une persistance opérationnelle au `JobStore` +local. La migration est additive de V3 vers V4 : elle conserve les objets et +contrats de jobs locaux V3. Elle ne remplace pas la base métier V20 et ne +modifie pas la tranche financière V21. + +Le `JobStore` reste servi par son worker mono-propriétaire existant. Les +opérations de recherche n'introduisent ni second ordonnanceur ni exécution +concurrente implicite. L'admission des objets de recherche ne démarre pas, à +elle seule, une campagne. + +Cette tranche est qualifiée uniquement par des fixtures `SPECIMEN`, des +réponses injectées et un fournisseur de laboratoire loopback explicitement +configuré par le harness. Aucun fournisseur public n'est configuré ou qualifié +par ce contrat. Une absence de configuration ou d'autorisation de stockage +rend l'adapter concerné indisponible ; elle ne déclenche ni installation, ni +appel externe, ni repli vers un endpoint implicite. + +## 2. Contrats persistants distincts + +Les contrats versionnés de recherche assistée sont distincts des contrats +`labfy.local_plan.v1` et de session Web. Un cookie, un CSRF ou l'état de +l'interface ne font pas partie de leur contenu durable. + +| Objet | Contrat | Rôle durable | +| --- | --- | --- | +| `ResearchPlan` | `labfy.research_plan.v1` | intention bornée, seeds, actions exactes et empreintes d'entrée | +| `ResearchAction` | composant du plan | capability, fournisseur, endpoint, sujet, divulgation, classe de contact et plafonds | +| `ScopeGrant` | `labfy.scope_grant.v1` | décision liée à une enquête et à un plan, actions sélectionnées, exclusions, expiration et budgets | +| `ResearchCampaign` | `labfy.research_campaign.v1` | identité idempotente d'une campagne admise ; elle ne vaut pas démarrage automatique | +| `ResearchResult` | `labfy.research_result.v1` | résultat brut référencé par chemin relatif et empreinte de contenu | +| `ResearchReceipt` | `labfy.research_receipt.v1` | décision de policy associée au résultat, à l'action, au grant et à la campagne | + +L'admission est atomique : une même clé d'idempotence et le même contenu +retournent l'objet durable existant ; une même clé et un contenu différent sont +en conflit. Un plan ou un grant invalide ne laisse pas d'écriture partielle. +Un résultat ne peut pas être publié sans reçu visant une action explicitement +sélectionnée dans le grant de sa campagne. + +## 3. Scope, policy et destinations + +Avant tout contact, une décision est évaluée sur l'enquête, l'empreinte du +plan, l'action exacte, le grant et les budgets demandés. Les motifs observables +incluent notamment l'exclusion, la révocation, l'expiration, une enquête ou un +plan différent, une action non sélectionnée ou altérée, et un budget dépassé. +La révocation est durable et ne supprime pas l'historique du grant. + +La validation HTTP compare exactement le sujet, l'endpoint, le port et la +sélection. Le profil réseau est une allowlist d'endpoints et de ports, jamais +une règle par suffixe. Les adresses non publiquement routables sont refusées +par le contrat du transport de production. Une redirection, un CNAME, une URL +nouvelle ou une seed dérivée ne propage jamais le scope : chacun constitue une +nouvelle destination à décider explicitement. + +Le transport commun reste sans backend réseau lié et retourne donc +`UNAVAILABLE` sans contact. Son contrat interdit proxy, cookies, `netrc`, +authentification ambiante, redirection automatique et résolution fournie par +l'appelant. La variante libcurl est testée uniquement avec le routage de +fixture vers loopback ; son callback réseau refuse les adresses non publiques. +Les préfixes privés, locaux, documentaires et de benchmark ne sont pas des +adresses publiques. Les plafonds du corps compressé reçu sur le fil, du corps +décompressé et des en-têtes sont appliqués séparément, y compris sans +`Content-Length` et avec un transfert chunked. +Cela ne qualifie aucune configuration de production ni aucun fournisseur +externe. + +## 4. Adapters normalisateurs — CURRENT en laboratoire + +Les adapters suivants normalisent des données de fixture et préservent leurs +limites de périmètre : + +- DNS : types bornés A, AAAA, CNAME, MX, NS, TXT, SOA et PTR ; ni `ANY`, ni + AXFR, ni trace n'appartiennent au type public. Un cycle CNAME est signalé et + ne crée pas de piste suivante implicite. +- RDAP : sélection du service depuis un bootstrap versionné et borné ; le + bootstrap routé ne vaut jamais scope pour le service retourné. +- CDX : correspondance d'URL ou d'hôte exact, captures normalisées et curseur + explicite ; il n'y a pas d'élargissement de la cible. +- Brave et SearXNG : disponibilité explicite (`UNAVAILABLE_CONFIG` ou + `UNAVAILABLE_STORAGE_AUTHORIZATION`) tant que l'endpoint, la référence de + secret et l'autorisation nécessaires ne sont pas réunis. Aucun secret n'est + persisté dans ces contrats. +- Page : production de texte inerte borné ; scripts, liens, sous-ressources et + pièces jointes ne sont ni exécutés ni suivis. + +Ces résultats peuvent indiquer une `next_piste`, qui reste une information à +préparer et approuver ; elle ne confère aucune autorisation dérivée. + +## 5. Publication et provenance C + +Le cœur C sépare la décision, l'artefact brut, le résultat et le reçu. Le +résultat conserve un chemin relatif d'artefact et son SHA-256 ; la publication +atomique exige le reçu de policy correspondant. Cette provenance permet de +revenir au grant, à l'action et à la campagne, sans assimiler un contenu reçu +à une identité confirmée ou à une autorisation de poursuivre. + +Les résultats de laboratoire du parcours Web sont stockés comme artefacts +privés de l'espace de travail de test. Le bridge expose un snapshot de +recherche, pas un accès arbitraire au répertoire d'artefacts ni une base de +provenance indépendante du cœur C. + +La publication fichier/SQLite utilise un journal privé créé avant le renommage +final. Il lie l'identité déterministe du résultat à l'empreinte attendue. Si le +processus s'interrompt après le renommage, le rejeu de la même campagne vérifie +ce journal et l'artefact, puis enregistre atomiquement résultat et reçu sans +recontacter le fournisseur. Un état possédé incohérent est compensé avant de +retourner une erreur. Le journal est supprimé après publication durable ; cette +reprise n'ajoute ni table ni numéro de schéma. + +## 6. Poste Web local — préparation et décision humaine + +Le panneau de recherche du poste Web local prépare un plan depuis une +sélection et une révision de snapshot précises. L'interface présente les +actions et leurs divulgations, puis exige une décision explicite : + +1. préparer un plan ; +2. sélectionner ou refuser les actions pour former le `ScopeGrant` ; +3. admettre une campagne pour les seules actions accordées ; +4. préparer et approuver séparément une seconde vague éventuelle. + +L'action refusée reste refusée ; elle ne devient pas admissible au lancement +d'une autre action. La révocation du grant est une mutation explicite et +durable. Une révision de sélection périmée, un identifiant étranger ou une +forme de requête invalide sont refusés. + +Les sessions, cookies et CSRF restent des contrôles de la surface Web et sont +distincts des contrats ci-dessus. Les validations couvrent l'isolation de deux +espaces de travail synthétiques A/B : un plan, grant, campagne ou résultat de +l'espace A n'est pas visible ni réutilisable dans l'espace B. + +## 7. Procédure de validation autorisée + +Les seuls parcours documentés ici utilisent les harnesses synthétiques du +dépôt et leurs répertoires temporaires. Les contrôles Web dédiés sont : + +```sh +python3 prototypes/web-graph/tests/test_research_web.py +node prototypes/web-graph/tests/test_research_browser.mjs +``` + +Ils démarrent leur fournisseur `SPECIMEN` de loopback à durée de vie bornée et +ne nécessitent ni endpoint public, ni jeton, ni enquête réelle. Les tests C +`test_research_store`, `test_research_policy`, `test_research_transport` et +`test_research_adapters` couvrent respectivement la migration/persistance, les +décisions de policy, les bornes du transport/libcurl et les normalisations de +fixtures. Leur exécution relève du harness de validation de la tranche ; elle +ne constitue pas une autorisation de contacter des services externes. + +## 8. Ce qui reste TARGET ou non qualifié + +Restent hors de ce livrable : qualification et configuration d'un fournisseur +public, gestion opérationnelle de secrets, exécution de recherche hors +laboratoire, propagation automatique de scope, ordonnancement autonome de +recherche, ainsi que le serveur, le protocole d'événements, le renderer et le +packaging Web de production. Le Web local ne change pas le statut de GTK comme +parcours fonctionnel existant. diff --git a/docs/ui/WEB_GTK_PARITY.md b/docs/ui/WEB_GTK_PARITY.md new file mode 100644 index 0000000..533f594 --- /dev/null +++ b/docs/ui/WEB_GTK_PARITY.md @@ -0,0 +1,21 @@ +# Matrice de parité Web avant retrait GTK + +> État : `CURRENT` local — `LABFY_WEB_FINAL_INTERFACE_AND_REMOVE_GTK_V1`. +> Les contrôles utilisent exclusivement les workspaces `SPECIMEN`. + +| Fonction GTK historique | Équivalent Web CURRENT | Test Web | État | +| --- | --- | --- | --- | +| Graphe, sélection, pan, zoom, focus et retour | SVG interactif central, recherche et actions contextuelles | `test_workbench_browser.mjs` | remplacé | +| Positions et zoom persistés | Projection C et positions épinglées conservées au rafraîchissement | `test_workbench_populated_browser.mjs` | remplacé | +| Arbre / détails d'entité, preuve et relation | Drawer Détails et inspecteur à onglets | `test_local_workspace_import_browser.mjs` | remplacé | +| Provenance et revue | Onglets Provenance et Observations, promotion explicite | `test_j9_browser.mjs` | remplacé | +| Activité, tâches et annulation | Drawer Tâches, JobStore V4 et contrôles de file | `test_j8_runtime_browser.mjs` | remplacé | +| Actions OSINT contextuelles | Capability → service → job, plan/grant/campagne explicites | `test_research_browser.mjs` | remplacé | +| Import, aperçu et analyse de preuve | Réception privée, preview dérivé, analyses C | `test_local_workspace_import_browser.mjs` | remplacé | +| Rapports | Prévisualisation et dossier hors ligne vérifiable | `test_j9_browser.mjs` | remplacé | +| Dialogues de création GTK et formulaires spécialisés | Parcours non exposés par le bridge Web actuel | aucun | retiré, pas de logique métier supprimée | +| Widgets OCR de rendu GTK | Données, correction et provenance conservées dans services/DAO ; renderer retiré | tests C de services conservés | retiré, renderer seulement | + +Les parcours retirés ne constituaient pas une API métier : ils dépendaient du +renderer GTK. Les DAO, services, migrations V20, fondation financière V21 et +JobStore V4 restent hors de cette suppression. diff --git a/docs/ui/WEB_WORKBENCH.md b/docs/ui/WEB_WORKBENCH.md index 8b91cb1..99b3baa 100644 --- a/docs/ui/WEB_WORKBENCH.md +++ b/docs/ui/WEB_WORKBENCH.md @@ -1,20 +1,23 @@ # Poste Web local — guide d’utilisation -> **Statut CURRENT local :** poste utilisable au-dessus des services C et du -> JobStore V3 existants, depuis une bibliothèque d'enquêtes explicitement +> **Statut CURRENT local :** interface utilisateur Web unique, utilisable au-dessus des services C et du +> JobStore V4 existants, depuis une bibliothèque d'enquêtes explicitement > choisie. Les validations emploient des fixtures `SPECIMEN`. Il ne constitue > ni une autorisation d’ouvrir une enquête réelle, ni un service distant. ## Organisation -À l'ouverture, la bibliothèque affiche les enquêtes locales enregistrées et +À l'ouverture, le lanceur `tools/labfy` démarre ou rejoint l’instance loopback +possédée, ouvre le navigateur et établit une session HttpOnly locale sans code +manuel. La bibliothèque affiche les enquêtes locales enregistrées et permet d'en créer une avec un titre explicite. Une enquête ouverte reste la seule enquête active de cette instance ; le poste n'en restaure pas une autre automatiquement. Le titre et la génération de la bibliothèque identifient le contexte affiché, afin qu'une réponse tardive d'une enquête précédente ne le repeuple pas. -Le graphe reste la surface principale. La barre haute porte l’identité de +Le graphe reste la surface principale. La coque est **Agent | Graphe | +Activité**, plus un tiroir transversal. La barre haute porte l’identité de l’enquête, le statut local et la recherche. La rangée suivante change de projection (`Réseau`, `Preuves`, `Chronologie`, `Infrastructure locale`) sans créer une seconde vérité métier. @@ -93,10 +96,10 @@ Une date sans fuseau ou invalide reste non positionnable. Lancer le poste local sur une bibliothèque explicitement choisie : ```bash -make web PORT=8081 LIBRARY=/chemin/vers/la-bibliotheque-locale +LABFY_LIBRARY=/chemin/vers/la-bibliotheque-locale tools/labfy ``` -L’écoute reste loopback, la session est authentifiée et les mutations exigent +L’écoute reste loopback, la session est HttpOnly/SameSite et les mutations exigent le jeton CSRF. Le poste n’expose pas le répertoire des preuves et n’installe aucun outil. Les projections vides, erreurs, annulations et limites sont des états explicites ; elles ne prouvent jamais une absence d’information. diff --git a/include/core/application.h b/include/core/application.h deleted file mode 100644 index 7dd9d6e..0000000 --- a/include/core/application.h +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * @file application.h - * @brief Interface publique du cycle de vie de l'application. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_APPLICATION_H -#define LABFY_INVESTIGATION_APPLICATION_H - -/** - * @brief Représentation opaque d'une session d'enquête. - */ -typedef struct InvestigationSession InvestigationSession; - -/** - * @brief Représentation opaque de l'application. - * - * Les détails GTK sont volontairement masqués au reste du programme. - */ -typedef struct Application Application; - -/** - * @brief Crée et initialise une application Labfy Investigation. - * - * @return Une nouvelle application, ou NULL en cas d'échec. - */ -Application *application_new(void); - -/** - * @brief Lance la boucle principale de l'application. - * - * @param application Application à exécuter. - * @param argc Nombre d'arguments de la ligne de commande. - * @param argv Tableau des arguments de la ligne de commande. - * - * @return Code de sortie retourné par GTK. - */ -int application_run( - Application *application, - int argc, - char **argv -); - -/** - * @brief Retourne la session d'enquête actuellement ouverte. - * - * Le pointeur retourné appartient à l'application. - * Le code appelant ne doit pas fermer cette session. - * - * @param application Application concernée. - * - * @return La session active, ou NULL si aucune enquête n'est ouverte - * ou si application vaut NULL. - */ -const InvestigationSession *application_get_session( - const Application *application -); - -/** - * @brief Libère les ressources possédées par l'application. - * - * Cette fonction accepte NULL. - * - * @param application Application à libérer. - */ -void application_free( - Application *application -); - -#endif diff --git a/include/core/local_job_store.h b/include/core/local_job_store.h index 40fe896..9432b75 100644 --- a/include/core/local_job_store.h +++ b/include/core/local_job_store.h @@ -1,6 +1,6 @@ /****************************************************************************** * @file local_job_store.h - * @brief Stockage opérationnel V3 des jobs et plans locaux J5/J8. + * @brief Stockage opérationnel V4 des jobs, plans locaux et grants assistés. ******************************************************************************/ #ifndef LABFY_INVESTIGATION_LOCAL_JOB_STORE_H #define LABFY_INVESTIGATION_LOCAL_JOB_STORE_H @@ -9,7 +9,7 @@ G_BEGIN_DECLS -#define LOCAL_JOB_STORE_SCHEMA_VERSION 3 +#define LOCAL_JOB_STORE_SCHEMA_VERSION 4 #define LOCAL_JOB_STORE_MAX_JOBS 128U #define LOCAL_JOB_STORE_MAX_ATTEMPTS 3U #define LOCAL_JOB_DIAGNOSTIC_MAX 2048U diff --git a/include/core/research_adapter_cdx.h b/include/core/research_adapter_cdx.h new file mode 100644 index 0000000..cded6b8 --- /dev/null +++ b/include/core/research_adapter_cdx.h @@ -0,0 +1,14 @@ +#ifndef LABFY_INVESTIGATION_RESEARCH_ADAPTER_CDX_H +#define LABFY_INVESTIGATION_RESEARCH_ADAPTER_CDX_H +#include "core/research_contracts.h" +G_BEGIN_DECLS +typedef enum { RESEARCH_CDX_EXACT_URL, RESEARCH_CDX_EXACT_HOST } ResearchCdxMatch; +typedef struct { const char *original_url; const char *timestamp; const char *digest; + guint status_code; } ResearchCdxRow; +typedef struct { const ResearchCdxRow *rows; gsize row_count; const char *next_cursor; } ResearchCdxFixture; +typedef struct { GPtrArray *captures; char *next_cursor; gboolean next_piste; } ResearchCdxResult; +gboolean research_adapter_cdx_normalize(const ResearchAction *action, + ResearchCdxMatch match,const ResearchCdxFixture *fixture,ResearchCdxResult *out,GError **error); +void research_cdx_result_clear(ResearchCdxResult *result); +G_END_DECLS +#endif diff --git a/include/core/research_adapter_dns.h b/include/core/research_adapter_dns.h new file mode 100644 index 0000000..28c7e20 --- /dev/null +++ b/include/core/research_adapter_dns.h @@ -0,0 +1,23 @@ +#ifndef LABFY_INVESTIGATION_RESEARCH_ADAPTER_DNS_H +#define LABFY_INVESTIGATION_RESEARCH_ADAPTER_DNS_H +#include "core/research_contracts.h" +G_BEGIN_DECLS +typedef enum { RESEARCH_DNS_A, RESEARCH_DNS_AAAA, RESEARCH_DNS_CNAME, + RESEARCH_DNS_MX, RESEARCH_DNS_NS, RESEARCH_DNS_TXT, RESEARCH_DNS_SOA, + RESEARCH_DNS_PTR } ResearchDnsType; +typedef enum { RESEARCH_DNS_STATUS_OK, RESEARCH_DNS_STATUS_NXDOMAIN, + RESEARCH_DNS_STATUS_NODATA, RESEARCH_DNS_STATUS_SERVFAIL, + RESEARCH_DNS_STATUS_TIMEOUT } ResearchDnsStatus; +typedef struct { ResearchDnsType type; const char *owner; const char *value; + guint ttl; guint preference; } ResearchDnsRecord; +typedef struct { ResearchDnsStatus status; const ResearchDnsRecord *records; + gsize record_count; } ResearchDnsFixture; +typedef struct { ResearchDnsStatus status; GPtrArray *records; + gboolean cname_cycle; gboolean next_piste; } ResearchDnsResult; +/** CONTRACT: ANY, AXFR et trace n'existent pas dans le type public. */ +gboolean research_adapter_dns_normalize(const ResearchAction *action, + ResearchDnsType requested_type, const ResearchDnsFixture *fixture, + ResearchDnsResult *out, GError **error); +void research_dns_result_clear(ResearchDnsResult *result); +G_END_DECLS +#endif diff --git a/include/core/research_adapter_page.h b/include/core/research_adapter_page.h new file mode 100644 index 0000000..29f20d8 --- /dev/null +++ b/include/core/research_adapter_page.h @@ -0,0 +1,13 @@ +#ifndef LABFY_INVESTIGATION_RESEARCH_ADAPTER_PAGE_H +#define LABFY_INVESTIGATION_RESEARCH_ADAPTER_PAGE_H +#include "core/research_contracts.h" +G_BEGIN_DECLS +typedef struct { const char *content_type; const guint8 *body; gsize body_size; } ResearchPageFixture; +typedef struct { char *inert_text; gboolean links_ignored; gboolean attachments_ignored; + gboolean next_piste; } ResearchPageResult; +/** CONTRACT: produit du texte inerte; aucun script, lien, sous-ressource ou attachment n'est suivi. */ +gboolean research_adapter_page_normalize(const ResearchAction *action, + const ResearchPageFixture *fixture,gsize max_text_bytes,ResearchPageResult *out,GError **error); +void research_page_result_clear(ResearchPageResult *result); +G_END_DECLS +#endif diff --git a/include/core/research_adapter_rdap.h b/include/core/research_adapter_rdap.h new file mode 100644 index 0000000..7a8f4cc --- /dev/null +++ b/include/core/research_adapter_rdap.h @@ -0,0 +1,19 @@ +#ifndef LABFY_INVESTIGATION_RESEARCH_ADAPTER_RDAP_H +#define LABFY_INVESTIGATION_RESEARCH_ADAPTER_RDAP_H +#include "core/research_contracts.h" +G_BEGIN_DECLS +typedef enum { RESEARCH_RDAP_DOMAIN_SERVICE, RESEARCH_RDAP_IPV4_SERVICE, + RESEARCH_RDAP_IPV6_SERVICE } ResearchRdapServiceKind; +typedef struct { ResearchRdapServiceKind kind; const char *prefix; + const char *base_url; } ResearchRdapBootstrapEntry; +typedef struct { const ResearchRdapBootstrapEntry *entries; gsize entry_count; + const char *fetched_at; const char *expires_at; const char *etag; } ResearchRdapBootstrap; +typedef struct { char *service_url; guint prefix_length; char *cache_fetched_at; + char *cache_expires_at; char *cache_etag; gboolean next_piste; } ResearchRdapResult; +/** WHY: le bootstrap routé ne vaut jamais autorisation sur l'objet retourné. */ +gboolean research_adapter_rdap_select(const ResearchAction *action, + ResearchRdapServiceKind kind, const ResearchRdapBootstrap *bootstrap, + ResearchRdapResult *out, GError **error); +void research_rdap_result_clear(ResearchRdapResult *result); +G_END_DECLS +#endif diff --git a/include/core/research_adapter_search.h b/include/core/research_adapter_search.h new file mode 100644 index 0000000..8ba6d80 --- /dev/null +++ b/include/core/research_adapter_search.h @@ -0,0 +1,19 @@ +#ifndef LABFY_INVESTIGATION_RESEARCH_ADAPTER_SEARCH_H +#define LABFY_INVESTIGATION_RESEARCH_ADAPTER_SEARCH_H +#include "core/research_contracts.h" +G_BEGIN_DECLS +typedef enum { RESEARCH_SEARCH_BRAVE, RESEARCH_SEARCH_SEARXNG } ResearchSearchProvider; +typedef enum { RESEARCH_SEARCH_AVAILABLE, RESEARCH_SEARCH_UNAVAILABLE_CONFIG, + RESEARCH_SEARCH_UNAVAILABLE_STORAGE_AUTHORIZATION } ResearchSearchAvailability; +typedef struct { ResearchSearchProvider provider; const char *endpoint; + const char *secret_reference; gboolean storage_authorized; } ResearchSearchConfig; +typedef struct { const char *title; const char *url; const char *snippet; } ResearchSearchHit; +typedef struct { ResearchSearchAvailability availability; GPtrArray *hits; + gboolean next_piste; } ResearchSearchResult; +ResearchSearchAvailability research_adapter_search_availability(const ResearchSearchConfig *config); +gboolean research_adapter_search_normalize(const ResearchAction *action, + const ResearchSearchConfig *config,const ResearchSearchHit *hits,gsize hit_count, + ResearchSearchResult *out,GError **error); +void research_search_result_clear(ResearchSearchResult *result); +G_END_DECLS +#endif diff --git a/include/core/research_contracts.h b/include/core/research_contracts.h new file mode 100644 index 0000000..924b11f --- /dev/null +++ b/include/core/research_contracts.h @@ -0,0 +1,172 @@ +/****************************************************************************** + * @file research_contracts.h + * @brief Contrats versionnés de recherche assistée, sans exécution réseau. + ******************************************************************************/ +#ifndef LABFY_INVESTIGATION_RESEARCH_CONTRACTS_H +#define LABFY_INVESTIGATION_RESEARCH_CONTRACTS_H + +#include + +G_BEGIN_DECLS + +#define RESEARCH_PLAN_CONTRACT "labfy.research_plan.v1" +#define RESEARCH_GRANT_CONTRACT "labfy.scope_grant.v1" +#define RESEARCH_CAMPAIGN_CONTRACT "labfy.research_campaign.v1" +#define RESEARCH_RESULT_CONTRACT "labfy.research_result.v1" +#define RESEARCH_RECEIPT_CONTRACT "labfy.research_receipt.v1" + +typedef enum { + RESEARCH_SEED_DOMAIN, + RESEARCH_SEED_IP, + RESEARCH_SEED_HTTP_URL, + RESEARCH_SEED_EMAIL, + RESEARCH_SEED_SEARCH_TERM +} ResearchSeedKind; + +typedef enum { + RESEARCH_CONTACT_NONE, + RESEARCH_CONTACT_THIRD_PARTY, + RESEARCH_CONTACT_TARGET +} ResearchContactClass; + +typedef struct { + ResearchSeedKind kind; + const char *subject; +} ResearchSeed; + +typedef struct { + const char *action_id; + const char *capability_id; + const char *provider_id; + const char *endpoint; + const char *subject; + ResearchContactClass contact; + const char *disclosure; + guint max_requests; + guint64 max_response_bytes; + guint max_active_ms; +} ResearchAction; + +typedef struct { + const char *contract; + const char *plan_id; + const char *idempotency_key; + const char *content_fingerprint; + const char *input_fingerprint; + guint64 input_revision; + const char *created_at; + const ResearchSeed *seeds; + gsize seed_count; + const ResearchAction *actions; + gsize action_count; +} ResearchPlan; + +typedef enum { + RESEARCH_ACTION_AUTHORIZE, + RESEARCH_ACTION_DEFER, + RESEARCH_ACTION_REFUSE +} ResearchActionDecisionCode; + +typedef struct { + const char *action_id; + ResearchActionDecisionCode code; +} ResearchActionDecision; + +typedef struct { + const char *contract; + const char *grant_id; + const char *investigation_id; + const char *idempotency_key; + const char *content_fingerprint; + const char *plan_fingerprint; + const char *created_at; + const char *expires_at; + const char *const *selected_action_ids; + gsize selected_action_count; + const char *const *excluded_subjects; + gsize excluded_subject_count; + guint max_requests; + guint64 max_response_bytes; + guint max_active_ms; +} ScopeGrant; + +typedef struct { + const char *contract; + const char *campaign_id; + const char *investigation_id; + const char *grant_id; + const char *idempotency_key; + const char *content_fingerprint; + const char *created_at; +} ResearchCampaign; + +typedef struct { + const char *contract; + const char *result_id; + const char *campaign_id; + const char *action_id; + const char *raw_artifact_relative_path; + const char *content_sha256; + const char *status; +} ResearchResult; + +typedef struct { + const char *contract; + const char *receipt_id; + const char *result_id; + const char *campaign_id; + const char *grant_id; + const char *action_id; + const char *decided_at; + const char *decision_code; +} ResearchReceipt; + +typedef enum { + RESEARCH_POLICY_ALLOW, + RESEARCH_POLICY_DENY_EXCLUDED, + RESEARCH_POLICY_DENY_REVOKED, + RESEARCH_POLICY_DENY_EXPIRED, + RESEARCH_POLICY_DENY_INVESTIGATION, + RESEARCH_POLICY_DENY_PLAN, + RESEARCH_POLICY_DENY_ACTION, + RESEARCH_POLICY_DENY_ACTION_CONTENT, + RESEARCH_POLICY_DENY_BUDGET +} ResearchPolicyDecision; + +typedef struct { + const char *investigation_id; + const char *plan_fingerprint; + const ResearchAction *action; + const char *now; + guint requested_requests; + guint64 requested_response_bytes; + guint requested_active_ms; +} ResearchPolicyRequest; + +/** + * Vérifie la forme complète d'un plan avant toute écriture. + * CONTRACT: les identités et empreintes sont stables et toutes les actions + * sont bornées. INVARIANT: une seed dérivée n'accorde jamais de scope. + */ +gboolean research_plan_validate(const ResearchPlan *plan, GError **error); + +/** + * Vérifie le contenu durable d'un grant, à l'exclusion des cookies/CSRF qui + * n'appartiennent pas à ce contrat persistant. + */ +gboolean research_scope_grant_validate(const ScopeGrant *grant, + GError **error); +gboolean research_campaign_validate(const ResearchCampaign *campaign, + GError **error); +gboolean research_result_validate(const ResearchResult *result, + GError **error); +gboolean research_receipt_validate(const ResearchReceipt *receipt, + GError **error); + +const char *research_seed_kind_code(ResearchSeedKind kind); +const char *research_contact_class_code(ResearchContactClass contact); +const char *research_policy_decision_code(ResearchPolicyDecision decision); +const char *research_action_decision_code(ResearchActionDecisionCode decision); + +G_END_DECLS +#endif diff --git a/include/core/research_http_transport_curl.h b/include/core/research_http_transport_curl.h new file mode 100644 index 0000000..0fc738e --- /dev/null +++ b/include/core/research_http_transport_curl.h @@ -0,0 +1,28 @@ +#ifndef LABFY_INVESTIGATION_RESEARCH_HTTP_TRANSPORT_CURL_H +#define LABFY_INVESTIGATION_RESEARCH_HTTP_TRANSPORT_CURL_H + +#include "core/research_transport.h" + +G_BEGIN_DECLS + +/** + * CONTRACT: exécute une requête préalablement validée, sans état ambiant. + * INVARIANT: le callback socket refuse toute adresse qui n'est pas publique. + */ +gboolean research_http_transport_curl_execute( + const ResearchTransportRequest *request, ResearchTransportReply *out_reply, + GError **error); + +#ifdef RESEARCH_TRANSPORT_ENABLE_TEST_HOOKS +/** + * TEST-ONLY: route une autorité exacte vers une adresse loopback finie. + * Cette fonction n'existe pas dans l'API de production. + */ +gboolean research_http_transport_curl_execute_fixture( + const ResearchTransportRequest *request, const char *authority, + const char *loopback_address, ResearchTransportReply *out_reply, + GError **error); +#endif + +G_END_DECLS +#endif diff --git a/include/core/research_policy.h b/include/core/research_policy.h new file mode 100644 index 0000000..456f2a2 --- /dev/null +++ b/include/core/research_policy.h @@ -0,0 +1,55 @@ +/****************************************************************************** + * @file research_policy.h + * @brief Policy pure pour les destinations de recherche assistée V1. + ******************************************************************************/ +#ifndef LABFY_INVESTIGATION_RESEARCH_POLICY_H +#define LABFY_INVESTIGATION_RESEARCH_POLICY_H + +#include "core/research_contracts.h" + +G_BEGIN_DECLS + +typedef struct { + const guint16 *allowed_ports; + gsize allowed_port_count; + const char *const *allowed_endpoints; + gsize allowed_endpoint_count; +} ResearchNetworkProfile; + +typedef struct { + char *scheme; + char *host; + guint16 port; + char *path_and_query; +} ResearchHttpTarget; + +typedef enum { + RESEARCH_REDIRECT_REQUIRES_DECISION, + RESEARCH_REDIRECT_INVALID +} ResearchRedirectDecision; + +/** + * CONTRACT: valide l'action et le grant exacts avant tout contact réseau. + * WHY: le profil décrit une allowlist, jamais une règle par suffixe. + * INVARIANT: sujet, endpoint, port et sélection sont comparés exactement. + */ +gboolean research_policy_validate_http_action( + const ResearchAction *action, const ScopeGrant *grant, + const ResearchNetworkProfile *profile, ResearchHttpTarget *out_target, + GError **error); + +/** INVARIANT: seules les adresses globalement routables sont acceptées. */ +gboolean research_policy_address_is_public(const char *address); + +/** + * CONTRACT: une redirection valide reste une nouvelle destination à décider. + * Cette fonction ne propage jamais l'autorisation de l'action initiale. + */ +ResearchRedirectDecision research_policy_check_redirect( + const char *location, const ResearchNetworkProfile *profile, + ResearchHttpTarget *out_target, GError **error); + +void research_http_target_clear(ResearchHttpTarget *target); + +G_END_DECLS +#endif diff --git a/include/core/research_store.h b/include/core/research_store.h new file mode 100644 index 0000000..83033f9 --- /dev/null +++ b/include/core/research_store.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * @file research_store.h + * @brief Persistance V4 des autorisations de recherche assistée. + ******************************************************************************/ +#ifndef LABFY_INVESTIGATION_RESEARCH_STORE_H +#define LABFY_INVESTIGATION_RESEARCH_STORE_H + +#include "core/local_job_store.h" +#include "core/research_contracts.h" + +G_BEGIN_DECLS + +/** + * Admet atomiquement un plan et ses seeds/actions exactes. + * CONTRACT: même clé et même contenu retourne le même objet durable; une même + * clé avec un contenu différent est un conflit. + * INVARIANT: aucune action invalide ne laisse un plan partiellement écrit. + */ +gboolean research_store_admit_plan(LocalJobStore *store, + const ResearchPlan *plan, + gboolean *out_reused, GError **error); + +/** + * Admet un grant lié au plan et matérialise les sujets/provider/endpoints + * autorisés au moment de la décision. Toutes les décisions humaines sont + * persistées dans la même transaction. REFUSE est terminal et rend l'action + * durablement inadmissible; la vague 2 exige une vague 1 autorisée, exécutée + * et documentée par son résultat et son reçu. + */ +gboolean research_store_admit_grant(LocalJobStore *store, + const ScopeGrant *grant, + const ResearchActionDecision *decisions, + gsize decision_count, + const char *decided_at, + gboolean *out_reused, GError **error); + +/** Révoque durablement un grant sans supprimer son historique. */ +gboolean research_store_revoke_grant(LocalJobStore *store, + const char *grant_id, + const char *revoked_at, + GError **error); + +/** Admet l'identité durable d'une campagne; ne démarre aucun travail. */ +gboolean research_store_admit_campaign(LocalJobStore *store, + const ResearchCampaign *campaign, + gboolean *out_reused, GError **error); + +/** + * Enregistre atomiquement le résultat brut et le reçu de policy correspondant. + * INVARIANT: le reçu doit viser une action explicitement sélectionnée du grant + * de la campagne; aucun résultat orphelin n'est publié. + */ +gboolean research_store_record_result(LocalJobStore *store, + const ResearchResult *result, + const ResearchReceipt *receipt, + GError **error); + +/** + * Évalue un usage exact du grant sans créer de job ni réserver de budget. + * WHY: l'unique worker existant reste le seul ordonnanceur; cette fonction + * rend la décision de policy observable avant toute admission ultérieure. + * INVARIANT: exclusion, révocation et expiration sont des refus explicites; + * redirection, CNAME ou nouvelle URL ne correspondent jamais par construction. + */ +gboolean research_store_policy_decide(LocalJobStore *store, + const char *grant_id, + const ResearchPolicyRequest *request, + ResearchPolicyDecision *out_decision, + GError **error); + +G_END_DECLS +#endif diff --git a/include/core/research_transport.h b/include/core/research_transport.h new file mode 100644 index 0000000..0bdf31d --- /dev/null +++ b/include/core/research_transport.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * @file research_transport.h + * @brief Transport borné et sans autorité implicite pour la recherche V1. + ******************************************************************************/ +#ifndef LABFY_INVESTIGATION_RESEARCH_TRANSPORT_H +#define LABFY_INVESTIGATION_RESEARCH_TRANSPORT_H + +#include "core/research_policy.h" + +G_BEGIN_DECLS + +typedef enum { + RESEARCH_TRANSPORT_OK, + RESEARCH_TRANSPORT_UNAVAILABLE, + RESEARCH_TRANSPORT_CANCELLED, + RESEARCH_TRANSPORT_TIMEOUT, + RESEARCH_TRANSPORT_RATE_LIMITED, + RESEARCH_TRANSPORT_FORBIDDEN, + RESEARCH_TRANSPORT_REDIRECT, + RESEARCH_TRANSPORT_TOO_LARGE, + RESEARCH_TRANSPORT_INVALID_RESPONSE, + RESEARCH_TRANSPORT_FAILED +} ResearchTransportState; + +typedef struct { + const char *name; + const char *value; +} ResearchHeader; + +typedef struct { + const ResearchAction *action; + const ScopeGrant *grant; + const ResearchNetworkProfile *profile; + const char *method; + const ResearchHeader *headers; + gsize header_count; + guint64 max_compressed_bytes; + guint64 max_decompressed_bytes; + guint64 max_header_bytes; + GCancellable *cancellable; +} ResearchTransportRequest; + +typedef struct { + ResearchTransportState state; + guint status_code; + guint retry_after_seconds; + gboolean retry_after_present; + gboolean body_is_compressed; + GBytes *body; + GHashTable *headers; + char *redirect_location; + char *diagnostic; +} ResearchTransportReply; + +/** + * CONTRACT: la production n'utilise ni proxy, cookies, netrc, auth ambiante, + * redirection automatique, ni résolution fournie par l'appelant. + * CURRENT: aucun backend réseau n'est lié; retourne UNAVAILABLE sans contact. + */ +gboolean research_transport_execute(const ResearchTransportRequest *request, + ResearchTransportReply *out_reply, + GError **error); + +gboolean research_transport_request_validate( + const ResearchTransportRequest *request, ResearchHttpTarget *out_target, + GError **error); +void research_transport_reply_clear(ResearchTransportReply *reply); +const char *research_transport_state_code(ResearchTransportState state); + +#ifdef RESEARCH_TRANSPORT_ENABLE_TEST_HOOKS +typedef struct { + guint status_code; + const ResearchHeader *headers; + gsize header_count; + const guint8 *body; + gsize body_size; + gboolean compressed; + guint64 decompressed_size; + const char *peer_address; + const char *redirect_location; + gboolean timed_out; + gboolean unavailable; +} ResearchTransportFixture; + +/** TEST-ONLY: réponse finie injectée, sans socket ni résolution réseau. */ +gboolean research_transport_execute_fixture( + const ResearchTransportRequest *request, + const ResearchTransportFixture *fixture, + const char *const *loopback_authorities, gsize authority_count, + ResearchTransportReply *out_reply, GError **error); +#endif + +G_END_DECLS +#endif diff --git a/include/views/application_message_dialog.h b/include/views/application_message_dialog.h deleted file mode 100644 index 7530869..0000000 --- a/include/views/application_message_dialog.h +++ /dev/null @@ -1,136 +0,0 @@ -/****************************************************************************** - * @file application_message_dialog.h - * @brief Fenêtre modale affichant un message à l'utilisateur. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_APPLICATION_MESSAGE_DIALOG_H -#define LABFY_INVESTIGATION_APPLICATION_MESSAGE_DIALOG_H - -#include - -/** - * @brief Nature du message affiché. - */ -typedef enum -{ - APPLICATION_MESSAGE_DIALOG_ERROR, - APPLICATION_MESSAGE_DIALOG_WARNING, - APPLICATION_MESSAGE_DIALOG_INFORMATION -} ApplicationMessageDialogType; - -/** - * @brief Callback appelé à la fermeture d'un dialogue de confirmation. - * - * Le callback est appelé une seule fois après un clic sur l'un des boutons - * ou après une fermeture manuelle de la fenêtre. - * - * @param confirmed TRUE si l'utilisateur confirme, sinon FALSE. - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*ApplicationMessageDialogConfirmationCallback)( - gboolean confirmed, - gpointer user_data -); - -/** - * @brief Callback appelé par l'action facultative d'un dialogue détaillé. - * - * @param user_data Données associées à l'action. - */ -typedef void (*ApplicationMessageDialogActionCallback)( - gpointer user_data -); - -/** - * @brief Affiche une fenêtre modale contenant un message. - * - * Les chaînes sont copiées par les widgets GTK. - * - * @param parent_window Fenêtre parente, ou NULL. - * @param message_type Type de message. - * @param title Titre de la fenêtre, ou NULL. - * @param message Message principal, ou NULL. - */ -void application_message_dialog_present( - GtkWindow *parent_window, - ApplicationMessageDialogType message_type, - const char *title, - const char *message -); - -/** - * @brief Affiche un message accompagné d'un contenu textuel défilable. - * - * Le contenu détaillé est affiché dans une zone monospace sélectionnable. - * Les chaînes sont copiées par les widgets GTK. - * - * @param parent_window Fenêtre parente, ou NULL. - * @param message_type Type de message. - * @param title Titre de la fenêtre, ou NULL. - * @param message Message principal, ou NULL. - * @param details Contenu détaillé, ou NULL. - */ -void application_message_dialog_present_details( - GtkWindow *parent_window, - ApplicationMessageDialogType message_type, - const char *title, - const char *message, - const char *details -); - -/** - * @brief Affiche un message détaillé avec une action facultative. - * - * Le dialogue devient propriétaire de action_data lorsque l'affichage est - * créé. Les données sont libérées avec action_data_destroy à sa fermeture. - * - * @param parent_window Fenêtre parente, ou NULL. - * @param message_type Type de message. - * @param title Titre de la fenêtre, ou NULL. - * @param message Message principal, ou NULL. - * @param details Contenu détaillé, ou NULL. - * @param action_label Libellé de l'action, ou NULL. - * @param action_callback Callback de l'action, ou NULL. - * @param action_data Données transmises au callback. - * @param action_data_destroy Destructeur des données, ou NULL. - */ -void application_message_dialog_present_details_action( - GtkWindow *parent_window, - ApplicationMessageDialogType message_type, - const char *title, - const char *message, - const char *details, - const char *action_label, - ApplicationMessageDialogActionCallback action_callback, - gpointer action_data, - GDestroyNotify action_data_destroy -); - -/** - * @brief Affiche un dialogue modal demandant une confirmation. - * - * Le bouton d'annulation transmet FALSE. Le bouton de confirmation transmet - * TRUE. Fermer la fenêtre manuellement équivaut à une annulation. - * - * callback et user_data sont empruntés jusqu'à la fermeture du dialogue. - * confirm_label peut être NULL ou vide pour utiliser « Confirmer ». - * - * @param parent_window Fenêtre parente, ou NULL. - * @param message_type Type de message. - * @param title Titre de la fenêtre, ou NULL. - * @param message Message principal, ou NULL. - * @param confirm_label Libellé du bouton de confirmation, ou NULL. - * @param callback Callback facultatif recevant la réponse. - * @param user_data Données empruntées transmises au callback. - */ -void application_message_dialog_present_confirmation( - GtkWindow *parent_window, - ApplicationMessageDialogType message_type, - const char *title, - const char *message, - const char *confirm_label, - ApplicationMessageDialogConfirmationCallback callback, - gpointer user_data -); - -#endif diff --git a/include/views/create_investigation_dialog.h b/include/views/create_investigation_dialog.h deleted file mode 100644 index 8af568d..0000000 --- a/include/views/create_investigation_dialog.h +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** - * @file create_investigation_dialog.h - * @brief Interface publique du dialogue de création d'une enquête. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_CREATE_INVESTIGATION_DIALOG_H -#define LABFY_INVESTIGATION_CREATE_INVESTIGATION_DIALOG_H - -#include - -/** - * @brief Callback appelé lorsque le dialogue est validé ou annulé. - * - * Lors d'une validation réussie : - * - * - parent_directory contient le dossier parent sélectionné ; - * - investigation_name contient le nom nettoyé de l'enquête. - * - * Lors d'une annulation : - * - * - parent_directory vaut NULL ; - * - investigation_name vaut NULL. - * - * Les chaînes transmises restent valides uniquement pendant l'appel du - * callback. Le code appelant doit les copier s'il souhaite les conserver. - * - * @param parent_directory Dossier parent sélectionné, ou NULL. - * @param investigation_name Nom de l'enquête, ou NULL. - * @param user_data Données utilisateur fournies lors de l'ouverture. - */ -typedef void (*CreateInvestigationDialogCallback)( - const char *parent_directory, - const char *investigation_name, - gpointer user_data -); - -/** - * @brief Présente le dialogue de création d'une nouvelle enquête. - * - * Le dialogue permet : - * - * - de sélectionner un dossier parent existant ; - * - de saisir le nom de l'enquête ; - * - de valider ou d'annuler la création. - * - * Cette fonction ne crée aucun fichier et n'accède pas à SQLite. - * - * @param parent_window Fenêtre GTK parente, ou NULL. - * @param callback Fonction appelée lors de la validation ou de l'annulation. - * @param user_data Données transmises au callback. - */ -void create_investigation_dialog_present( - GtkWindow *parent_window, - CreateInvestigationDialogCallback callback, - gpointer user_data -); - -#endif diff --git a/include/views/create_person_dialog.h b/include/views/create_person_dialog.h deleted file mode 100644 index eae02b9..0000000 --- a/include/views/create_person_dialog.h +++ /dev/null @@ -1,54 +0,0 @@ -/****************************************************************************** - * @file create_person_dialog.h - * @brief Formulaire GTK de création d'une personne observée. - ******************************************************************************/ -#ifndef LABFY_INVESTIGATION_CREATE_PERSON_DIALOG_H -#define LABFY_INVESTIGATION_CREATE_PERSON_DIALOG_H -#include "core/person_entity_service.h" -#include "core/evidence_staging.h" -#include "models/evidence_record.h" -#include "models/person_evidence_selection.h" -#include "core/task_manager.h" -#include "core/tool_registry.h" -#include -G_BEGIN_DECLS -/** @brief Résultat opaque possédé par le callback. */ -typedef struct CreatePersonDialogResult CreatePersonDialogResult; -/** @brief Callback appelé après validation ou annulation. */ -typedef void (*CreatePersonDialogCallback)(CreatePersonDialogResult *result, - gpointer user_data); -typedef gboolean (*CreatePersonDialogSessionCheck)(gpointer user_data); -/** - * @brief Présente le formulaire de création d'une personne. - * @param parent Fenêtre parente. - * @param evidence_records Preuves disponibles empruntées. - * @param callback Callback de fin. - * @param user_data Données privées du callback. - * @return TRUE si le dialogue a été présenté. - */ -gboolean create_person_dialog_present(GtkWindow *parent, - Database *database, const GPtrArray *evidence_records, - const char *investigation_root_path, - TaskManager *task_manager, const ToolInfo *tesseract_tool, - CreatePersonDialogSessionCheck session_check, - CreatePersonDialogCallback callback, gpointer user_data, - GDestroyNotify user_data_destroy); -/** @brief Libère un résultat. */ -void create_person_dialog_result_free(CreatePersonDialogResult *result); -/** @brief Retourne les données empruntées du résultat. */ -const PersonEntityInput *create_person_dialog_result_get_input( - const CreatePersonDialogResult *result); -const PersonEvidenceSelection *create_person_dialog_result_get_evidence_selection( - const CreatePersonDialogResult *result); -EvidenceStaging *create_person_dialog_result_steal_staging( - CreatePersonDialogResult *result); -const GPtrArray *create_person_dialog_result_get_ocr_runs( - const CreatePersonDialogResult *result); -const GPtrArray *create_person_dialog_result_get_factual_relations( - const CreatePersonDialogResult *result); -const GPtrArray *create_person_dialog_result_get_ocr_projections( - const CreatePersonDialogResult *result); -gboolean create_person_dialog_test_overlay_has_region(GtkWindow *window); -guint64 create_person_dialog_test_ocr_generation(GtkWindow *window); -G_END_DECLS -#endif diff --git a/include/views/create_relation_dialog.h b/include/views/create_relation_dialog.h deleted file mode 100644 index 704d26b..0000000 --- a/include/views/create_relation_dialog.h +++ /dev/null @@ -1,211 +0,0 @@ -/****************************************************************************** - * @file create_relation_dialog.h - * @brief Dialogue GTK de préparation d'une relation entre deux entités. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_CREATE_RELATION_DIALOG_H -#define LABFY_INVESTIGATION_CREATE_RELATION_DIALOG_H - -#include - -G_BEGIN_DECLS - -/** - * @brief Résultat opaque produit par le dialogue. - */ -typedef struct CreateRelationDialogResult CreateRelationDialogResult; -typedef struct RelationRecord RelationRecord; - -/** - * @brief Codes d'erreur produits par CreateRelationDialog. - */ -typedef enum -{ - CREATE_RELATION_DIALOG_ERROR_INVALID_ARGUMENT, - CREATE_RELATION_DIALOG_ERROR_EMPTY_TARGETS, - CREATE_RELATION_DIALOG_ERROR_MEMORY, - CREATE_RELATION_DIALOG_ERROR_INVALID_DATA -} CreateRelationDialogError; - -/** - * @brief Domaine d'erreur du dialogue. - */ -#define CREATE_RELATION_DIALOG_ERROR \ - create_relation_dialog_error_quark() - -/** - * @brief Callback appelé après validation ou annulation. - * - * En cas de validation, result appartient au callback et doit être libéré - * avec create_relation_dialog_result_free(). - * - * En cas d'annulation, result vaut NULL. - * - * @param result Résultat possédé par le callback, ou NULL. - * @param user_data Données privées fournies lors de l'ouverture. - */ -typedef void (*CreateRelationDialogCallback)( - CreateRelationDialogResult *result, - gpointer user_data -); - -/** - * @brief Retourne le domaine d'erreur du dialogue. - */ -GQuark create_relation_dialog_error_quark(void); - -/** - * @brief Présente le dialogue de création d'une relation. - * - * entities doit contenir des pointeurs EntityRecord valides. Le dialogue - * copie tous les identifiants et libellés nécessaires et ne conserve aucun - * pointeur vers les modèles fournis. - * - * L'entité source est retirée de la liste des cibles. - * - * Cette fonction ne crée aucune relation et n'accède pas à SQLite. - * - * @param parent Fenêtre GTK parente. - * @param source_entity_identifier UUID de l'entité source. - * @param entities Tableau de EntityRecord. - * @param evidence_records Tableau de EvidenceRecord disponibles. - * @param investigation_root_path Racine canonique de l'enquête. - * @param callback Fonction appelée après validation ou annulation. - * @param user_data Données privées transmises au callback. - * @param error Emplacement facultatif recevant une erreur immédiate. - * - * @return TRUE si le dialogue a été créé et présenté. - */ -gboolean create_relation_dialog_present( - GtkWindow *parent, - const char *source_entity_identifier, - const GPtrArray *entities, - const GPtrArray *relation_types, - const GPtrArray *evidence_records, - const char *investigation_root_path, - CreateRelationDialogCallback callback, - gpointer user_data, - GError **error -); - -/** - * @brief Présente le dialogue prérempli pour modifier une relation. - * - * La source et la cible sont conservées ; les champs métier sont modifiables. - * Le dialogue ne réalise aucune écriture SQLite. - * - * @param parent Fenêtre GTK parente. - * @param relation_record Relation existante à modifier. - * @param entities Tableau de EntityRecord. - * @param evidence_records Tableau de EvidenceRecord disponibles. - * @param selected_evidence_identifiers UUID des preuves déjà liées. - * @param investigation_root_path Racine canonique de l'enquête. - * @param callback Fonction appelée après validation ou annulation. - * @param user_data Données privées transmises au callback. - * @param error Emplacement facultatif recevant une erreur immédiate. - * - * @return TRUE si le dialogue a été créé et présenté. - */ -gboolean edit_relation_dialog_present( - GtkWindow *parent, - const RelationRecord *relation_record, - const GPtrArray *entities, - const GPtrArray *relation_types, - const GPtrArray *evidence_records, - const GPtrArray *selected_evidence_identifiers, - const char *investigation_root_path, - CreateRelationDialogCallback callback, - gpointer user_data, - GError **error -); - -/** - * @brief Valide les valeurs obligatoires d'une relation. - * - * Cette fonction est indépendante de l'affichage et pourra être testée - * sans ouvrir de fenêtre GTK. - * - * @param source_entity_identifier UUID de l'entité source. - * @param target_entity_identifier UUID de l'entité cible. - * @param relation_type Type de relation non vide. - * @param confidence Confiance comprise entre 0 et 100. - * @param error Emplacement facultatif recevant une erreur. - * - * @return TRUE lorsque les valeurs sont valides. - */ -gboolean create_relation_dialog_validate_values( - const char *source_entity_identifier, - const char *target_entity_identifier, - const char *relation_type, - gint confidence, - GError **error -); - -/** - * @brief Libère un résultat. - * - * Cette fonction accepte NULL. - */ -void create_relation_dialog_result_free( - CreateRelationDialogResult *result -); - -/** - * @brief Retourne l'UUID de l'entité source. - */ -const char *create_relation_dialog_result_get_source_identifier( - const CreateRelationDialogResult *result -); - -/** - * @brief Retourne l'UUID de l'entité cible. - */ -const char *create_relation_dialog_result_get_target_identifier( - const CreateRelationDialogResult *result -); - -/** - * @brief Retourne le type de relation. - */ -const char *create_relation_dialog_result_get_relation_type( - const CreateRelationDialogResult *result -); -gint64 create_relation_dialog_result_get_relation_type_identifier( - const CreateRelationDialogResult *result); -const char *create_relation_dialog_result_get_relation_type_code( - const CreateRelationDialogResult *result); - -/** - * @brief Retourne le libellé facultatif. - */ -const char *create_relation_dialog_result_get_label( - const CreateRelationDialogResult *result -); - -/** - * @brief Retourne la justification facultative. - */ -const char *create_relation_dialog_result_get_justification( - const CreateRelationDialogResult *result -); - -/** - * @brief Retourne le niveau de confiance. - */ -gint create_relation_dialog_result_get_confidence( - const CreateRelationDialogResult *result -); - -/** - * @brief Retourne les UUID de preuves sélectionnés. - * - * @param result Résultat validé du dialogue. - * - * @return Tableau emprunté d'UUID, ou NULL. - */ -const GPtrArray *create_relation_dialog_result_get_evidence_identifiers( - const CreateRelationDialogResult *result); - -G_END_DECLS - -#endif diff --git a/include/views/create_social_account_dialog.h b/include/views/create_social_account_dialog.h deleted file mode 100644 index 51a487d..0000000 --- a/include/views/create_social_account_dialog.h +++ /dev/null @@ -1,67 +0,0 @@ -/****************************************************************************** - * @file create_social_account_dialog.h - * @brief Dialogue GTK de création d'un compte social observé. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_CREATE_SOCIAL_ACCOUNT_DIALOG_H -#define LABFY_INVESTIGATION_CREATE_SOCIAL_ACCOUNT_DIALOG_H - -#include "models/evidence_record.h" - -#include - -G_BEGIN_DECLS - -/** @brief Résultat opaque du dialogue de compte social. */ -typedef struct CreateSocialAccountDialogResult CreateSocialAccountDialogResult; - -/** @brief Callback appelé après validation ou annulation. */ -typedef void (*CreateSocialAccountDialogCallback)( - CreateSocialAccountDialogResult *result, - gpointer user_data -); - -/** - * @brief Présente le formulaire de création d'un compte social. - * - * Le tableau de preuves est uniquement emprunté pendant cet appel ; les - * informations nécessaires au formulaire sont copiées. - * - * @param parent Fenêtre parente. - * @param evidence_records Tableau facultatif de EvidenceRecord. - * @param callback Callback de fin. - * @param user_data Données privées du callback. - * @return TRUE si le dialogue a été présenté. - */ -gboolean create_social_account_dialog_present( - GtkWindow *parent, - const GPtrArray *evidence_records, - CreateSocialAccountDialogCallback callback, - gpointer user_data -); - -/** @brief Libère un résultat, y compris toutes ses chaînes. */ -void create_social_account_dialog_result_free( - CreateSocialAccountDialogResult *result -); - -/** @brief Retourne le code de la plateforme sélectionnée. */ -const char *create_social_account_dialog_result_get_platform(const CreateSocialAccountDialogResult *result); -/** @brief Retourne l'URL complète du profil. */ -const char *create_social_account_dialog_result_get_profile_url(const CreateSocialAccountDialogResult *result); -/** @brief Retourne le pseudonyme affiché. */ -const char *create_social_account_dialog_result_get_username(const CreateSocialAccountDialogResult *result); -/** @brief Retourne l'identifiant stable facultatif de la plateforme. */ -const char *create_social_account_dialog_result_get_platform_identifier(const CreateSocialAccountDialogResult *result); -/** @brief Retourne la date UTC de première observation. */ -const char *create_social_account_dialog_result_get_first_observed_at(const CreateSocialAccountDialogResult *result); -/** @brief Retourne l'état observé du compte. */ -const char *create_social_account_dialog_result_get_account_state(const CreateSocialAccountDialogResult *result); -/** @brief Retourne les notes factuelles facultatives. */ -const char *create_social_account_dialog_result_get_notes(const CreateSocialAccountDialogResult *result); -/** @brief Retourne l'UUID de la preuve associée, ou NULL. */ -const char *create_social_account_dialog_result_get_evidence_identifier(const CreateSocialAccountDialogResult *result); - -G_END_DECLS - -#endif diff --git a/include/views/dialog_geometry.h b/include/views/dialog_geometry.h deleted file mode 100644 index f3f44c7..0000000 --- a/include/views/dialog_geometry.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef LABFY_DIALOG_GEOMETRY_H -#define LABFY_DIALOG_GEOMETRY_H - -#include - -typedef struct { - int initial_width; - int initial_height; - int minimum_width; - int minimum_height; -} LabfyDialogGeometry; - -LabfyDialogGeometry labfy_dialog_geometry_calculate( - int workarea_width, int workarea_height); - -void labfy_dialog_apply_standard_geometry( - GtkWindow *window, GtkWindow *parent); - -void labfy_dialog_prepare( - GtkWindow *window, - GtkWindow *parent, - gboolean modal, - gboolean destroy_with_parent); - -void labfy_dialog_present(GtkWindow *window); - -void labfy_paned_apply_initial_ratio( - GtkPaned *paned, double ratio, int minimum_start, int minimum_end); -gboolean labfy_paned_initial_ratio_applied(GtkPaned *paned); - -#endif diff --git a/include/views/document_authenticity_editor.h b/include/views/document_authenticity_editor.h deleted file mode 100644 index b43e3df..0000000 --- a/include/views/document_authenticity_editor.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef LABFY_DOCUMENT_AUTHENTICITY_EDITOR_H -#define LABFY_DOCUMENT_AUTHENTICITY_EDITOR_H -#include "database/database.h" -#include -G_BEGIN_DECLS -typedef struct DocumentAuthenticityEditor DocumentAuthenticityEditor; -DocumentAuthenticityEditor *document_authenticity_editor_new(Database *database,const char *evidence_identifier); -GtkWidget *document_authenticity_editor_get_widget(DocumentAuthenticityEditor *editor); -gboolean document_authenticity_editor_refresh(DocumentAuthenticityEditor *editor,GError **error); -void document_authenticity_editor_free(DocumentAuthenticityEditor *editor); -G_END_DECLS -#endif diff --git a/include/views/document_identity_misuse_editor.h b/include/views/document_identity_misuse_editor.h deleted file mode 100644 index 0a2d25d..0000000 --- a/include/views/document_identity_misuse_editor.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef LABFY_DOCUMENT_IDENTITY_MISUSE_EDITOR_H -#define LABFY_DOCUMENT_IDENTITY_MISUSE_EDITOR_H -#include "database/database.h" -#include -G_BEGIN_DECLS -typedef struct DocumentIdentityMisuseEditor DocumentIdentityMisuseEditor; -DocumentIdentityMisuseEditor *document_identity_misuse_editor_new(Database *database,const char *evidence_identifier); -GtkWidget *document_identity_misuse_editor_get_widget(DocumentIdentityMisuseEditor *editor); -gboolean document_identity_misuse_editor_refresh(DocumentIdentityMisuseEditor *editor,GError **error); -void document_identity_misuse_editor_free(DocumentIdentityMisuseEditor *editor); -G_END_DECLS -#endif diff --git a/include/views/eml_analysis_dialog.h b/include/views/eml_analysis_dialog.h deleted file mode 100644 index 1a56434..0000000 --- a/include/views/eml_analysis_dialog.h +++ /dev/null @@ -1,33 +0,0 @@ -/****************************************************************************** - * @file eml_analysis_dialog.h - * @brief Présentation en lecture seule d'une analyse EML. - ******************************************************************************/ -#ifndef LABFY_INVESTIGATION_EML_ANALYSIS_DIALOG_H -#define LABFY_INVESTIGATION_EML_ANALYSIS_DIALOG_H -#include "core/eml_processing.h" -#include "core/eml_integration.h" -#include "core/eml_pipeline_task.h" -#include -G_BEGIN_DECLS -/** @brief Callback recevant les propositions sélectionnées, ou NULL. */ -typedef void (*EmlAnalysisDialogCallback)(GPtrArray *proposals, - gpointer user_data); -/** - * @brief Affiche les métadonnées et indicateurs extraits d'une copie EML. - * @param parent Fenêtre parente. - * @param result Résultat emprunté pendant la construction de la fenêtre. - */ -void eml_analysis_dialog_present(GtkWindow *parent, - const EmlProcessingResult *result, EmlAnalysisDialogCallback callback, - gpointer user_data); -void eml_analysis_dialog_present_pipeline( - GtkWindow *parent, - const EmlPipelineResult *result, - const char *evidence_name, - const char *relative_path, - const char *source_sha256, - EmlAnalysisDialogCallback callback, - gpointer user_data -); -G_END_DECLS -#endif diff --git a/include/views/evidence_identity_ocr_dialog.h b/include/views/evidence_identity_ocr_dialog.h deleted file mode 100644 index 1cc0019..0000000 --- a/include/views/evidence_identity_ocr_dialog.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef LABFY_EVIDENCE_IDENTITY_OCR_DIALOG_H -#define LABFY_EVIDENCE_IDENTITY_OCR_DIALOG_H - -#include "core/tool_registry.h" -#include "core/background_task.h" -#include "models/entity_record.h" -#include "models/identity_ocr.h" -#include - -G_BEGIN_DECLS - -typedef struct EvidenceIdentityOcrDialogResult - EvidenceIdentityOcrDialogResult; -typedef gboolean (*EvidenceIdentityOcrDialogSessionCheck)(gpointer user_data); -typedef void (*EvidenceIdentityOcrDialogCallback)( - EvidenceIdentityOcrDialogResult *result, gpointer user_data); - -gboolean evidence_identity_ocr_dialog_file_is_compatible( - const char *file_path); -gboolean evidence_identity_ocr_dialog_present( - GtkWindow *parent, const char *file_path, const GPtrArray *persons, - const char *preselected_person_identifier, - const ToolInfo *tesseract_tool, - EvidenceIdentityOcrDialogSessionCheck session_check, - EvidenceIdentityOcrDialogCallback callback, - gpointer user_data, GDestroyNotify user_data_destroy, - GError **error); -gboolean evidence_identity_ocr_dialog_present_review( - GtkWindow *parent,const char *file_path,const GPtrArray *persons, - const char *preselected_person_identifier, - const IdentityOcrRun *persisted_run, - EvidenceIdentityOcrDialogSessionCheck session_check, - EvidenceIdentityOcrDialogCallback callback, - gpointer user_data,GDestroyNotify user_data_destroy,GError **error); -void evidence_identity_ocr_dialog_result_free( - EvidenceIdentityOcrDialogResult *result); -gboolean evidence_identity_ocr_dialog_result_has_ocr( - const EvidenceIdentityOcrDialogResult *result); -const char *evidence_identity_ocr_dialog_result_get_person_identifier( - const EvidenceIdentityOcrDialogResult *result); -const char *evidence_identity_ocr_dialog_result_get_temporary_identifier( - const EvidenceIdentityOcrDialogResult *result); -const char *evidence_identity_ocr_dialog_result_get_sha256( - const EvidenceIdentityOcrDialogResult *result); -guint64 evidence_identity_ocr_dialog_result_get_size( - const EvidenceIdentityOcrDialogResult *result); -const char *evidence_identity_ocr_dialog_result_get_mime_type( - const EvidenceIdentityOcrDialogResult *result); -IdentityOcrRun *evidence_identity_ocr_dialog_result_steal_run( - EvidenceIdentityOcrDialogResult *result); -GtkWindow *evidence_identity_ocr_dialog_result_get_dialog( - const EvidenceIdentityOcrDialogResult *result); -void evidence_identity_ocr_dialog_finish_import( - GtkWindow *dialog, const GError *error); -void evidence_identity_ocr_dialog_set_submission_task( - GtkWindow *dialog, BackgroundTask *task); - -G_END_DECLS - -#endif diff --git a/include/views/evidence_import_dialog.h b/include/views/evidence_import_dialog.h deleted file mode 100644 index 2e63c95..0000000 --- a/include/views/evidence_import_dialog.h +++ /dev/null @@ -1,176 +0,0 @@ -/****************************************************************************** - * @file evidence_import_dialog.h - * @brief Dialogue GTK de saisie des métadonnées d'une preuve. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_EVIDENCE_IMPORT_DIALOG_H -#define LABFY_INVESTIGATION_EVIDENCE_IMPORT_DIALOG_H - -#include - -G_BEGIN_DECLS - -/** - * @brief Résultat opaque produit par le dialogue d'import. - */ -typedef struct EvidenceImportDialogResult EvidenceImportDialogResult; - -/** - * @brief Codes d'erreur produits par EvidenceImportDialog. - */ -typedef enum -{ - /** - * Un argument public est invalide. - */ - EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_ARGUMENT, - - /** - * Aucun type de preuve n'est disponible. - */ - EVIDENCE_IMPORT_DIALOG_ERROR_EMPTY_TYPES, - - /** - * Une allocation ou la création du dialogue a échoué. - */ - EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY, - - /** - * Les métadonnées saisies sont invalides. - */ - EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA -} EvidenceImportDialogError; - -/** - * @brief Domaine d'erreur du dialogue d'import. - */ -#define EVIDENCE_IMPORT_DIALOG_ERROR \ - evidence_import_dialog_error_quark() - -/** - * @brief Callback appelé après la fermeture du dialogue. - * - * En cas de validation, result est non NULL et appartient au callback. - * Il doit être libéré avec evidence_import_dialog_result_free(). - * - * En cas d'annulation, result vaut NULL. - * - * @param result Résultat possédé par le callback, ou NULL. - * @param user_data Données privées fournies lors de l'ouverture. - */ -typedef void (*EvidenceImportDialogCallback)( - EvidenceImportDialogResult *result, - gpointer user_data -); - -/** - * @brief Retourne le domaine d'erreur du dialogue. - * - * @return Quark GLib associé à EvidenceImportDialog. - */ -GQuark evidence_import_dialog_error_quark(void); - -/** - * @brief Présente le dialogue de saisie des métadonnées. - * - * Le chemin du fichier est affiché en lecture seule. - * - * evidence_types doit contenir des pointeurs EvidenceType valides. - * Le dialogue copie les codes et les libellés dont il a besoin : - * le tableau peut donc être libéré après le retour de cette fonction. - * - * Le type dont le code vaut "document" est sélectionné par défaut - * lorsqu'il est disponible. Sinon, le premier type est sélectionné. - * - * @param parent Fenêtre GTK parente. - * @param file_path Chemin du fichier sélectionné. - * @param evidence_types Tableau de EvidenceType. - * @param callback Fonction appelée après validation ou annulation. - * @param user_data Données privées transmises au callback. - * @param error Emplacement facultatif recevant une erreur immédiate. - * - * @return TRUE si le dialogue a été créé et présenté. - */ -gboolean evidence_import_dialog_present( - GtkWindow *parent, - const char *file_path, - const GPtrArray *evidence_types, - EvidenceImportDialogCallback callback, - gpointer user_data, - GError **error -); - -/** - * @brief Valide les valeurs obligatoires d'un import. - * - * Cette fonction ne dépend pas de l'affichage du dialogue et peut être - * testée sans ouvrir de fenêtre GTK. - * - * Le chemin doit désigner un fichier existant. - * Le code du type doit être non vide. - * La date doit être une date ISO 8601 valide comprenant un fuseau horaire. - * - * @param file_path Chemin du fichier à importer. - * @param type_identifier Code métier du type de preuve. - * @param collected_at Date de collecte au format ISO 8601. - * @param error Emplacement facultatif recevant une erreur. - * - * @return TRUE lorsque les valeurs sont valides. - */ -gboolean evidence_import_dialog_validate_values( - const char *file_path, - const char *type_identifier, - const char *collected_at, - GError **error -); - -/** - * @brief Libère le résultat produit par le dialogue. - * - * Cette fonction accepte NULL. - * - * @param result Résultat à libérer. - */ -void evidence_import_dialog_result_free( - EvidenceImportDialogResult *result -); - -/** - * @brief Retourne le code du type sélectionné. - * - * @return Chaîne empruntée, ou NULL. - */ -const char *evidence_import_dialog_result_get_type_identifier( - const EvidenceImportDialogResult *result -); - -/** - * @brief Retourne la date ISO 8601 de collecte. - * - * @return Chaîne empruntée, ou NULL. - */ -const char *evidence_import_dialog_result_get_collected_at( - const EvidenceImportDialogResult *result -); - -/** - * @brief Retourne la source renseignée. - * - * @return Chaîne empruntée, ou NULL lorsque la source est vide. - */ -const char *evidence_import_dialog_result_get_source( - const EvidenceImportDialogResult *result -); - -/** - * @brief Retourne la description renseignée. - * - * @return Chaîne empruntée, ou NULL lorsque la description est vide. - */ -const char *evidence_import_dialog_result_get_description( - const EvidenceImportDialogResult *result -); - -G_END_DECLS - -#endif diff --git a/include/views/evidence_metadata_dialog.h b/include/views/evidence_metadata_dialog.h deleted file mode 100644 index af3b66d..0000000 --- a/include/views/evidence_metadata_dialog.h +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * @file evidence_metadata_dialog.h - * @brief Dialogue de modification des métadonnées éditables d'une preuve. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_EVIDENCE_METADATA_DIALOG_H -#define LABFY_INVESTIGATION_EVIDENCE_METADATA_DIALOG_H - -#include "models/evidence_record.h" -#include "database/database.h" - -#include - -G_BEGIN_DECLS - -/** @brief Résultat opaque possédé du dialogue. */ -typedef struct EvidenceMetadataDialogResult EvidenceMetadataDialogResult; - -/** @brief Callback recevant le résultat possédé, ou NULL après annulation. */ -typedef void (*EvidenceMetadataDialogCallback)( - EvidenceMetadataDialogResult *result, gpointer user_data -); -typedef void (*EvidenceMetadataDialogAnalyzeCallback)( - GtkWindow *dialog, const char *evidence_identifier, - gboolean revise_existing, const char *ocr_run_identifier, - gpointer user_data); - -/** - * @brief Présente le dialogue prérempli de modification des métadonnées. - * @param parent Fenêtre parente. - * @param record Preuve empruntée. - * @param evidence_types Tableau emprunté de EvidenceType. - * @param callback Callback appelé une fois à la fermeture. - * @param user_data Données empruntées du callback. - * @return TRUE si la fenêtre a été créée. - */ -gboolean evidence_metadata_dialog_present( - GtkWindow *parent, - const EvidenceRecord *record, - const GPtrArray *evidence_types, - EvidenceMetadataDialogCallback callback, - gpointer user_data -); -gboolean evidence_metadata_dialog_present_with_ocr( - GtkWindow *parent, const EvidenceRecord *record, - const GPtrArray *evidence_types, Database *database, - const char *investigation_root, - EvidenceMetadataDialogAnalyzeCallback analyze_callback, - EvidenceMetadataDialogCallback callback, gpointer user_data); - -/** @brief Libère un résultat, ou accepte NULL. */ -void evidence_metadata_dialog_result_free(EvidenceMetadataDialogResult *result); -/** @brief Retourne le code de type emprunté. */ -const char *evidence_metadata_dialog_result_get_type_identifier( - const EvidenceMetadataDialogResult *result); -/** @brief Retourne la source empruntée, ou NULL. */ -const char *evidence_metadata_dialog_result_get_source( - const EvidenceMetadataDialogResult *result); -/** @brief Retourne la description empruntée, ou NULL. */ -const char *evidence_metadata_dialog_result_get_description( - const EvidenceMetadataDialogResult *result); - -G_END_DECLS -#endif diff --git a/include/views/file_dialog.h b/include/views/file_dialog.h deleted file mode 100644 index 5449f8a..0000000 --- a/include/views/file_dialog.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * @file file_dialog.h - * @brief Interface du dialogue de sélection d’un fichier de preuve. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_FILE_DIALOG_H -#define LABFY_INVESTIGATION_FILE_DIALOG_H - -#include - -/** - * @brief Fonction appelée après la fermeture du sélecteur. - * - * Cas possibles : - * - * - succès : file_path non NULL et error NULL ; - * - annulation : file_path NULL et error NULL ; - * - erreur : file_path NULL et error non NULL. - * - * Le chemin et l’erreur restent valides uniquement pendant l’appel. - * - * @param file_path Chemin local sélectionné, ou NULL. - * @param error Erreur de sélection, ou NULL. - * @param user_data Données transmises lors de l’ouverture. - */ -typedef void (*FileDialogCallback)( - const char *file_path, - const GError *error, - gpointer user_data -); - -/** - * @brief Fonction appelée après une sélection multiple. - * - * paths est un tableau emprunté de chemins locaux possédés par le dialogue. - * Il n'est valide que pendant l'appel. Une annulation transmet NULL sans - * erreur. - * - * @param paths Chemins sélectionnés, ou NULL. - * @param error Erreur de sélection, ou NULL. - * @param user_data Données fournies lors de l'ouverture. - */ -typedef void (*FileDialogMultipleCallback)( - const GPtrArray *paths, - const GError *error, - gpointer user_data -); - -/** - * @brief Ouvre un dialogue permettant de sélectionner un fichier. - * - * @param parent Fenêtre parente, éventuellement NULL. - * @param callback Fonction appelée lorsque le dialogue est terminé. - * @param user_data Données transmises au callback. - */ -void file_dialog_select_file( - GtkWindow *parent, - FileDialogCallback callback, - gpointer user_data -); - -/** - * @brief Ouvre un dialogue permettant de sélectionner plusieurs fichiers. - * @param parent Fenêtre parente, éventuellement NULL. - * @param callback Fonction appelée à la fermeture du dialogue. - * @param user_data Données transmises au callback. - */ -void file_dialog_select_files( - GtkWindow *parent, - FileDialogMultipleCallback callback, - gpointer user_data -); - -#endif diff --git a/include/views/folder_dialog.h b/include/views/folder_dialog.h deleted file mode 100644 index 843ed24..0000000 --- a/include/views/folder_dialog.h +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * @file folder_dialog.h - * @brief Interface du dialogue de sélection d'un dossier d'enquête. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_FOLDER_DIALOG_H -#define LABFY_INVESTIGATION_FOLDER_DIALOG_H - -#include - -/** - * @brief Fonction appelée après la fermeture du dialogue de sélection. - * - * @param folder_path Chemin du dossier sélectionné, ou NULL si l'utilisateur - * a annulé la sélection. - * @param user_data Données transmises lors de l'ouverture du dialogue. - * - * Le chemin reçu reste valide uniquement pendant l'appel de cette fonction. - * Il doit être copié si le code appelant souhaite le conserver. - * - * @param callback - * Fonction appelée lorsque le dialogue est fermé. - * - * Si l'utilisateur annule la sélection, - * folder_path vaut NULL. - */ -typedef void (*FolderDialogCallback)( - const char *folder_path, - gpointer user_data -); - -/** - * @brief Ouvre un dialogue permettant de sélectionner un dossier. - * - * @param parent Fenêtre parente du dialogue. - * Peut être NULL. - * @param callback Fonction appelée lorsque le dialogue est terminé. - * @param user_data Données transmises à la fonction de rappel. - */ -void folder_dialog_select_folder( - GtkWindow *parent, - FolderDialogCallback callback, - gpointer user_data -); - -#endif diff --git a/include/views/identity_ocr_language_loader.h b/include/views/identity_ocr_language_loader.h deleted file mode 100644 index f9f6466..0000000 --- a/include/views/identity_ocr_language_loader.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef IDENTITY_OCR_LANGUAGE_LOADER_H -#define IDENTITY_OCR_LANGUAGE_LOADER_H - -#include - -void identity_ocr_language_loader_start(GtkWindow *window, const char *tesseract_path, GtkDropDown *language_dropdown); - -#endif diff --git a/include/views/main_window.h b/include/views/main_window.h deleted file mode 100644 index e96dbe8..0000000 --- a/include/views/main_window.h +++ /dev/null @@ -1,758 +0,0 @@ -/****************************************************************************** - * @file main_window.h - * @brief Interface publique de la fenêtre principale. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_MAIN_WINDOW_H -#define LABFY_INVESTIGATION_MAIN_WINDOW_H - -#include "core/investigation_tree_model.h" -#include "widgets/investigation_tree_view.h" -#include "core/investigation_node.h" -#include "core/task_manager.h" -#include "widgets/evidence_category_model.h" -#include "models/evidence_record.h" -#include "models/osint_action_catalog.h" - -#include - -/** - * @brief Représentation opaque du graphe d'enquête. - */ -typedef struct InvestigationGraphModel InvestigationGraphModel; - -/** - * @brief Représentation opaque de la disposition du graphe. - */ -typedef struct InvestigationGraphLayout InvestigationGraphLayout; - -/** - * @brief Représentation opaque de la fenêtre principale. - */ -typedef struct MainWindow MainWindow; - -/** - * @brief Callback appelé lorsque l'utilisateur demande une nouvelle enquête. - * - * @param user_data Données utilisateur associées au callback. - */ -typedef void (*MainWindowNewInvestigationCallback)( - gpointer user_data -); - -/** - * @brief Callback appelé lorsque l'utilisateur demande - * l'import d'une preuve. - * - * @param user_data Données utilisateur associées au callback. - */ -typedef void (*MainWindowImportEvidenceCallback)( - gpointer user_data -); - -/** @brief Callback appelé pour ajouter un compte de réseau social. */ -typedef void (*MainWindowAddSocialAccountCallback)( - gpointer user_data -); -/** @brief Callback appelé pour ajouter une personne. */ -typedef void (*MainWindowAddPersonCallback)(gpointer user_data); - -/** - * @brief Callback appelé lorsque l'utilisateur revient au graphe. - * - * @param user_data Données utilisateur associées au callback. - */ -typedef void (*MainWindowShowGraphCallback)( - gpointer user_data -); - -/** - * @brief Callback appelé lorsqu'une preuve est sélectionnée. - * - * L'identifiant est emprunté et uniquement valide pendant l'appel. - * Une sélection vide ou une catégorie transmet NULL. - * - * @param evidence_identifier UUID de la preuve, ou NULL. - * @param user_data Données privées fournies par l'appelant. - */ -typedef void (*MainWindowEvidenceSelectionCallback)( - const char *evidence_identifier, - gpointer user_data -); - -/** - * @brief Callback appelé lorsque l'utilisateur demande une vérification. - * - * L'identifiant est emprunté et uniquement valide pendant l'appel. - * - * @param evidence_identifier UUID de la preuve. - * @param user_data Données privées du callback. - */ -typedef void (*MainWindowVerifyEvidenceCallback)( - const char *evidence_identifier, - gpointer user_data -); - -/** @brief Callback appelé pour modifier les métadonnées d'une preuve. */ -typedef void (*MainWindowEditEvidenceCallback)( - const char *evidence_identifier, - gpointer user_data -); -/** @brief Callback appelé pour analyser une preuve EML. */ -typedef void (*MainWindowAnalyzeEmlCallback)(const char *evidence_identifier, - gpointer user_data); -/** @brief Callback appelé pour analyser un RIB par OCR. */ -typedef void (*MainWindowAnalyzeRibCallback)(const char *evidence_identifier, - gpointer user_data); -typedef void (*MainWindowIdentityOcrCallback)( - const char *evidence_identifier, gboolean revise_existing, - const char *ocr_run_identifier, gpointer user_data); -/** @brief Callback appelé pour extraire les métadonnées d'une preuve. */ -typedef void (*MainWindowExtractMetadataCallback)(const char *evidence_identifier, - gpointer user_data); -/** @brief Callback appelé pour récupérer le mot de passe d'un PDF. */ -typedef void (*MainWindowRecoverPdfPasswordCallback)( - const char *evidence_identifier, gpointer user_data); - -/** - * @brief Callback appelé après le déplacement effectif d'un nœud. - * - * @param entity_identifier UUID de l'entité déplacée. - * @param x Coordonnée horizontale logique. - * @param y Coordonnée verticale logique. - * @param user_data Données privées du callback. - */ -typedef void (*MainWindowGraphNodeMovedCallback)( - const char *entity_identifier, - double x, - double y, - gpointer user_data -); -typedef void (*MainWindowGraphTransformChangedCallback)(gpointer user_data); - -typedef void (*MainWindowExtractionDropCallback)( - const char *file_path, - const char *target_entity_identifier, - gpointer user_data -); - -/** - * @brief Callback appelé lors d'une demande de réinitialisation du graphe. - * - * @param user_data Données privées du callback. - */ -typedef void (*MainWindowResetGraphLayoutCallback)( - gpointer user_data -); - -/** - * @brief Callback appelé lors d'une demande d'ajout d'une relation. - * - * @param source_entity_identifier UUID de l'entité source. - * @param user_data Données privées du callback. - */ -typedef void (*MainWindowAddRelationCallback)( - const char *source_entity_identifier, - gpointer user_data -); - -/** @brief Callback appelé pour modifier une relation. */ -typedef void (*MainWindowEditRelationCallback)( - const char *relation_identifier, - gpointer user_data -); -/** @brief Callback appelé pour supprimer une relation. */ -typedef void (*MainWindowDeleteRelationCallback)( - const char *relation_identifier, gpointer user_data); - -/** @brief Callback appelé quand une relation est sélectionnée. */ -typedef void (*MainWindowRelationSelectedCallback)( - const char *relation_identifier, - gpointer user_data -); - -/** @brief Callback appelé pour catégoriser une personne. */ -typedef void (*MainWindowPersonRoleCallback)(const char *entity_identifier, - PersonRole role, gpointer user_data); -/** @brief Callback appelé pour modifier la confiance d'une personne. */ -typedef void (*MainWindowPersonConfidenceCallback)( - const char *entity_identifier, gint confidence, gpointer user_data); - -/** - * @brief Callback appelé lors du déclenchement d'une action OSINT. - * - * @param action_identifier Identifiant stable de l'action. - * @param target_identifier UUID de la sélection ciblée. - * @param target_value Valeur métier ciblée. - * @param user_data Données privées fournies par l'appelant. - */ -typedef void (*MainWindowOsintActionCallback)( - const char *action_identifier, - const char *target_identifier, - const char *target_value, - gpointer user_data -); -/** @brief Callback appelé pour modifier le nom affiché d'une personne. */ -typedef void (*MainWindowPersonNameCallback)(const char *entity_identifier, - const char *display_name, gpointer user_data); -/** @brief Callback appelé pour gérer les preuves d'une personne. */ -typedef void (*MainWindowPersonEvidenceCallback)( - const char *entity_identifier, gpointer user_data); -/** @brief Callback appelé quand une entité est sélectionnée. */ -typedef void (*MainWindowEntitySelectedCallback)( - const char *entity_identifier, gpointer user_data); - -/** - * @brief Définit le callback de vérification d'une preuve. - * - * MainWindow relaie la demande provenant du Workspace. - * - * @param main_window Fenêtre principale. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void main_window_set_verify_evidence_callback( - MainWindow *main_window, - MainWindowVerifyEvidenceCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de modification de la preuve sélectionnée. - * @param main_window Fenêtre principale. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void main_window_set_edit_evidence_callback( - MainWindow *main_window, - MainWindowEditEvidenceCallback callback, - gpointer user_data -); -/** @brief Définit le callback d'analyse locale d'une preuve EML. */ -void main_window_set_analyze_eml_callback(MainWindow *main_window, - MainWindowAnalyzeEmlCallback callback, gpointer user_data); -/** @brief Définit le callback d'analyse OCR d'un RIB. */ -void main_window_set_analyze_rib_callback(MainWindow *main_window, - MainWindowAnalyzeRibCallback callback, gpointer user_data); -/** @brief Définit le callback d'extraction locale des métadonnées. */ -void main_window_set_extract_metadata_callback(MainWindow *main_window, - MainWindowExtractMetadataCallback callback, gpointer user_data); -/** @brief Définit le callback de récupération d'un mot de passe PDF. */ -void main_window_set_recover_pdf_password_callback(MainWindow *main_window, - MainWindowRecoverPdfPasswordCallback callback, gpointer user_data); -void main_window_set_identity_ocr_callback( - MainWindow *main_window, MainWindowIdentityOcrCallback callback, - gpointer user_data); - -/** - * @brief Définit le callback de fin de déplacement d'un nœud. - * - * MainWindow relaie uniquement l'événement provenant du Workspace. - * - * @param main_window Fenêtre principale. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void main_window_set_graph_node_moved_callback( - MainWindow *main_window, - MainWindowGraphNodeMovedCallback callback, - gpointer user_data -); -void main_window_set_graph_transform_changed_callback( - MainWindow *main_window, - MainWindowGraphTransformChangedCallback callback, - gpointer user_data); - -void main_window_set_extraction_drop_callback( - MainWindow *main_window, - MainWindowExtractionDropCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de demande de réinitialisation du graphe. - * - * MainWindow relaie uniquement la demande provenant du Workspace. - * - * @param main_window Fenêtre principale. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void main_window_set_reset_graph_layout_callback( - MainWindow *main_window, - MainWindowResetGraphLayoutCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de demande d'ajout d'une relation. - * - * MainWindow relaie uniquement la demande provenant du Workspace. - * - * @param main_window Fenêtre principale. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void main_window_set_add_relation_callback( - MainWindow *main_window, - MainWindowAddRelationCallback callback, - gpointer user_data -); - -/** @brief Définit le callback de modification d'une relation. */ -void main_window_set_edit_relation_callback( - MainWindow *main_window, - MainWindowEditRelationCallback callback, - gpointer user_data -); -/** @brief Définit le callback de suppression d'une relation. */ -void main_window_set_delete_relation_callback(MainWindow *main_window, - MainWindowDeleteRelationCallback callback, gpointer user_data); - -/** @brief Définit le callback de sélection d'une relation. */ -void main_window_set_relation_selected_callback( - MainWindow *main_window, - MainWindowRelationSelectedCallback callback, - gpointer user_data -); - -/** @brief Affiche les preuves associées à la relation sélectionnée. */ -void main_window_set_relation_evidences( - MainWindow *main_window, - const GPtrArray *evidence_records -); - -/** @brief Transmet les preuves associées à l'entité sélectionnée. */ -void main_window_set_person_evidences(MainWindow *main_window, - const GPtrArray *records); -void main_window_set_person_factual_relations(MainWindow *main_window, - const GPtrArray *relations, const GPtrArray *evidence_records,const GHashTable *profile_fields); - - -/** @brief Définit le callback de catégorisation d'une personne. */ -void main_window_set_person_role_callback(MainWindow *main_window, - MainWindowPersonRoleCallback callback, gpointer user_data); -/** @brief Définit le callback de confiance d'une personne. */ -void main_window_set_person_confidence_callback(MainWindow *main_window, - MainWindowPersonConfidenceCallback callback, gpointer user_data); - -/** - * @brief Définit le callback de déclenchement des actions OSINT. - * - * MainWindow relaie uniquement la demande provenant du Workspace. - * - * @param main_window Fenêtre principale. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void main_window_set_osint_action_callback( - MainWindow *main_window, - MainWindowOsintActionCallback callback, - gpointer user_data -); -/** @brief Définit le callback de modification du nom affiché. */ -void main_window_set_person_name_callback(MainWindow *main_window, - MainWindowPersonNameCallback callback, gpointer user_data); -/** @brief Définit le callback de gestion des preuves d'une personne. */ -void main_window_set_person_evidence_callback(MainWindow *main_window, - MainWindowPersonEvidenceCallback callback, gpointer user_data); -/** @brief Définit le callback de sélection d'une entité. */ -void main_window_set_entity_selected_callback(MainWindow *main_window, - MainWindowEntitySelectedCallback callback, gpointer user_data); -/** @brief Affiche les preuves de la personne sélectionnée. */ -void main_window_set_person_evidences(MainWindow *main_window, - const GPtrArray *evidence_records); - -/** - * @brief Définit le callback du bouton « Nouvelle enquête ». - * - * La fenêtre ne crée pas directement l'enquête. Elle transmet uniquement - * la demande au contrôleur. - * - * @param main_window Fenêtre principale. - * @param callback Fonction appelée lors du clic. - * @param user_data Données transmises au callback. - */ -void main_window_set_new_investigation_callback( - MainWindow *main_window, - MainWindowNewInvestigationCallback callback, - gpointer user_data -); - -/** - * @brief Crée une nouvelle fenêtre principale. - * - * MainWindow ne devient pas propriétaire de task_manager. - * - * @param application Application GTK. - * @param task_manager Gestionnaire de tâches de l'application. - * - * @return Nouvelle fenêtre, ou NULL en cas d'échec. - */ -MainWindow *main_window_new( - GtkApplication *application, - TaskManager *task_manager -); - -/** - * @brief Affiche la fenêtre principale. - * - * @param main_window Fenêtre à afficher. - */ -void main_window_present(MainWindow *main_window); - -/** - * @brief Retourne la fenêtre GTK associée. - * - * @param main_window Fenêtre principale. - * - * @return Fenêtre GTK. - */ -GtkWindow *main_window_get_window( - const MainWindow *main_window -); - -/** - * @brief Transmet un modèle d'arborescence à la fenêtre principale. - * - * La fenêtre principale ne devient pas propriétaire du modèle. - * Elle le transmet uniquement à la Sidebar. - * - * @param main_window Fenêtre principale à mettre à jour. - * @param tree_model Modèle d'arborescence en lecture seule. - */ -void main_window_set_tree_model( - MainWindow *main_window, - const InvestigationTreeModel *tree_model -); - -/** - * @brief Transmet le modèle des catégories de preuves à la Sidebar. - * - * MainWindow ne devient pas propriétaire du modèle. - * Le modèle doit rester valide pendant son affichage. - * - * Passer NULL vide l'onglet Preuves. - * - * @param main_window Fenêtre principale. - * @param evidence_category_model Modèle de catégories, ou NULL. - */ -void main_window_set_evidence_model( - MainWindow *main_window, - EvidenceCategoryModel *evidence_category_model -); - -/** - * @brief Met à jour l'identité de l'enquête affichée. - * - * La fonction met à jour : - * - * - le titre de la fenêtre ; - * - le texte de la barre d'état. - * - * Les chaînes sont copiées par GTK et restent la propriété de l'appelant. - * - * Cette fonction accepte des chaînes NULL ou vides. - * - * @param main_window Fenêtre principale à mettre à jour. - * @param investigation_name Nom persistant de l'enquête. - * @param investigation_root_path Chemin racine de l'enquête. - */ -void main_window_set_investigation( - MainWindow *main_window, - const char *investigation_name, - const char *investigation_root_path -); - -void main_window_set_tree_selection_callback( - MainWindow *main_window, - InvestigationTreeViewSelectionCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de sélection d'une preuve. - * - * MainWindow transmet uniquement le callback à la Sidebar. - * - * @param main_window Fenêtre principale. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void main_window_set_evidence_selection_callback( - MainWindow *main_window, - MainWindowEvidenceSelectionCallback callback, - gpointer user_data -); - -/** - * @brief Affiche dans le Workspace les informations du nœud sélectionné. - * - * La fenêtre principale ne devient pas propriétaire du nœud. - * - * @param main_window Fenêtre principale à mettre à jour. - * @param node Nœud sélectionné en lecture seule, ou NULL. - */ -void main_window_set_selected_node( - MainWindow *main_window, - const InvestigationNode *node -); - -/** - * @brief Affiche la fiche de la preuve sélectionnée. - * - * MainWindow ne conserve pas le EvidenceRecord. - * - * @param main_window Fenêtre principale. - * @param evidence_record Preuve sélectionnée, ou NULL. - */ -void main_window_set_selected_evidence( - MainWindow *main_window, - const EvidenceRecord *evidence_record -); -void main_window_set_identity_ocr_runs( - MainWindow *main_window, GPtrArray *owned_records); -void main_window_set_evidence_observations(MainWindow *main_window, - const GPtrArray *observations); -void main_window_set_observation_remove_callback(MainWindow *main_window, - void (*callback)(const char *, gpointer), gpointer user_data); -void main_window_set_eml_analysis_available( - MainWindow *main_window, - gboolean available -); - -/** @brief Transmet au workspace un chemin absolu validé pour l'aperçu. */ -void main_window_set_evidence_preview(MainWindow *main_window, - const char *file_path, const char *display_name); -void main_window_show_evidence_preview(MainWindow *main_window, - const char *investigation_root, const EvidenceRecord *record); - - -/** - * @brief Affiche l'état de chargement du graphe. - * - * MainWindow transmet uniquement la demande au Workspace. - * - * @param main_window Fenêtre principale. - */ -void main_window_set_graph_loading( - MainWindow *main_window -); - -/** - * @brief Affiche le graphe chargé et sa disposition dans le Workspace. - * - * MainWindow et Workspace empruntent graph_model et graph_layout. - * - * Passer NULL pour graph_layout conserve le placement automatique. - * - * @param main_window Fenêtre principale. - * @param graph_model Graphe emprunté, ou NULL. - * @param graph_layout Disposition empruntée, ou NULL. - */ -void main_window_set_graph( - MainWindow *main_window, - const InvestigationGraphModel *graph_model, - const InvestigationGraphLayout *graph_layout -); - -gboolean main_window_get_graph_view_transform( - MainWindow *main_window, double *zoom, double *offset_x, double *offset_y); -void main_window_set_graph_view_transform( - MainWindow *main_window, double zoom, double offset_x, double offset_y); - -/** @brief Sélectionne une relation dans le graphe affiché. */ -gboolean main_window_select_graph_relation( - MainWindow *main_window, - const char *relation_identifier -); -/** @brief Sélectionne une entité dans le graphe affiché. */ -gboolean main_window_select_graph_entity(MainWindow *main_window, - const char *entity_identifier); - -/** - * @brief Affiche une erreur de chargement du graphe. - * - * @param main_window Fenêtre principale. - * @param message Message d'erreur, ou NULL. - */ -void main_window_set_graph_error( - MainWindow *main_window, - const char *message -); - -/** - * @brief Détache le graphe du Workspace. - * - * Aucun graphe n'est libéré par MainWindow. - * - * @param main_window Fenêtre principale. - */ -void main_window_clear_graph( - MainWindow *main_window -); - -/** - * @brief Reconstruit visuellement la disposition automatique du graphe. - * - * Cette fonction ne modifie pas SQLite. - * - * @param main_window Fenêtre principale. - */ -void main_window_reset_graph_layout( - MainWindow *main_window -); - -/** - * @brief Met à jour le texte de la barre d'état. - * - * Si status_text vaut NULL, le texte par défaut est affiché. - * - * @param main_window Fenêtre principale. - * @param status_text Nouveau texte de statut, ou NULL. - */ -void main_window_set_status( - MainWindow *main_window, - const char *status_text -); - -/** - * @brief Transmet au workspace l'état d'un outil OSINT externe. - * - * @param main_window Fenêtre principale. - * @param tool_identifier Identifiant stable de l'outil. - * @param state État traduit par l'application. - * @param version Version détectée facultative. - */ -void main_window_set_osint_tool_state( - MainWindow *main_window, - const char *tool_identifier, - OsintActionToolState state, - const char *version -); - -/** - * @brief Callback appelé lorsque l'utilisateur demande l'ouverture - * d'une enquête existante. - * - * @param user_data Données utilisateur associées au callback. - */ -typedef void (*MainWindowOpenInvestigationCallback)( - gpointer user_data -); - -/** - * @brief Callback appelé lorsque l'utilisateur demande à quitter. - * - * @param user_data Données utilisateur associées au callback. - */ -typedef void (*MainWindowQuitCallback)( - gpointer user_data -); - -/** - * @brief Définit le callback du bouton « Ouvrir une enquête ». - * - * La fenêtre transmet uniquement la demande au contrôleur. - * - * @param main_window Fenêtre principale. - * @param callback Fonction appelée lors du clic. - * @param user_data Données transmises au callback. - */ -void main_window_set_open_investigation_callback( - MainWindow *main_window, - MainWindowOpenInvestigationCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback du bouton « Quitter ». - * - * MainWindow transmet uniquement la demande au contrôleur. - * - * @param main_window Fenêtre principale. - * @param callback Fonction appelée lors du clic. - * @param user_data Données transmises au callback. - */ -void main_window_set_quit_callback( - MainWindow *main_window, - MainWindowQuitCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de l'action « Importer une preuve ». - * - * MainWindow transmet uniquement la demande au contrôleur. - * - * @param main_window Fenêtre principale. - * @param callback Fonction appelée lors du clic. - * @param user_data Données transmises au callback. - */ -void main_window_set_import_evidence_callback( - MainWindow *main_window, - MainWindowImportEvidenceCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de l'action d'ajout d'un compte social. - * @param main_window Fenêtre principale. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void main_window_set_add_social_account_callback( - MainWindow *main_window, - MainWindowAddSocialAccountCallback callback, - gpointer user_data -); -/** @brief Définit le callback d'ajout d'une personne. */ -void main_window_set_add_person_callback(MainWindow *main_window, - MainWindowAddPersonCallback callback, gpointer user_data); - -/** - * @brief Définit le callback du bouton « Revenir au graphe ». - * - * MainWindow transmet uniquement la demande au contrôleur. - * - * @param main_window Fenêtre principale. - * @param callback Fonction appelée lors du clic, ou NULL. - * @param user_data Données transmises au callback. - */ -void main_window_set_show_graph_callback( - MainWindow *main_window, - MainWindowShowGraphCallback callback, - gpointer user_data -); - -/** - * @brief Active ou désactive l'action d'import d'une preuve. - * - * @param main_window Fenêtre principale. - * @param enabled TRUE pour autoriser l'import. - */ -void main_window_set_import_evidence_enabled( - MainWindow *main_window, - gboolean enabled -); - -/** - * @brief Active ou désactive l'ajout d'un compte social. - * @param main_window Fenêtre principale. - * @param enabled TRUE si une enquête est ouverte. - */ -void main_window_set_add_social_account_enabled( - MainWindow *main_window, - gboolean enabled -); -/** @brief Active ou désactive l'ajout d'une personne. */ -void main_window_set_add_person_enabled(MainWindow *main_window, gboolean enabled); - -/** - * @brief Libère les ressources de la fenêtre. - * - * @param main_window Fenêtre à détruire. - */ -void main_window_free(MainWindow *main_window); - -#endif diff --git a/include/views/manage_entity_evidence_dialog.h b/include/views/manage_entity_evidence_dialog.h deleted file mode 100644 index 0392ebc..0000000 --- a/include/views/manage_entity_evidence_dialog.h +++ /dev/null @@ -1,33 +0,0 @@ -/****************************************************************************** - * @file manage_entity_evidence_dialog.h - * @brief Dialogue de sélection des preuves associées à une entité. - ******************************************************************************/ -#ifndef LABFY_INVESTIGATION_MANAGE_ENTITY_EVIDENCE_DIALOG_H -#define LABFY_INVESTIGATION_MANAGE_ENTITY_EVIDENCE_DIALOG_H -#include "models/evidence_record.h" -#include "core/task_manager.h" -#include -G_BEGIN_DECLS -typedef void (*ManageEntityEvidenceDialogCallback)( - GPtrArray *selected_identifiers, gpointer user_data); -typedef void (*ManageEntityEvidenceImportCallback)(gpointer user_data); -/** - * @brief Présente la sélection multiple de preuves avec aperçu. - * @param parent Fenêtre parente. - * @param evidence_records Preuves disponibles empruntées. - * @param selected_identifiers UUID déjà associés empruntés. - * @param investigation_root_path Racine de l'enquête. - * @param callback Callback recevant un tableau possédé, ou NULL à l'annulation. - * @param user_data Données empruntées du callback. - * @param error Destination facultative d'une erreur immédiate. - * @return TRUE si le dialogue a été présenté. - */ -gboolean manage_entity_evidence_dialog_present(GtkWindow *parent, - const GPtrArray *evidence_records, const GPtrArray *selected_identifiers, - const char *investigation_root_path, - TaskManager *task_manager, - ManageEntityEvidenceDialogCallback callback, gpointer user_data, - ManageEntityEvidenceImportCallback import_callback, - GError **error); -G_END_DECLS -#endif diff --git a/include/views/metadata_analysis_dialog.h b/include/views/metadata_analysis_dialog.h deleted file mode 100644 index dbe2341..0000000 --- a/include/views/metadata_analysis_dialog.h +++ /dev/null @@ -1,25 +0,0 @@ -/****************************************************************************** - * @file metadata_analysis_dialog.h - * @brief Fenêtre de consultation des métadonnées extraites. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_METADATA_ANALYSIS_DIALOG_H -#define LABFY_INVESTIGATION_METADATA_ANALYSIS_DIALOG_H - -#include - -G_BEGIN_DECLS - -/** - * @brief Affiche une synthèse ExifTool dans une fenêtre défilable. - * @param parent Fenêtre parente facultative. - * @param summary Métadonnées lisibles empruntées. - * @param json_path Chemin emprunté de la sortie JSON conservée. - * @param version Version empruntée d'ExifTool. - */ -void metadata_analysis_dialog_present(GtkWindow *parent, const char *summary, - const char *json_path, const char *version); - -G_END_DECLS - -#endif diff --git a/include/views/osint_dns_review_dialog.h b/include/views/osint_dns_review_dialog.h deleted file mode 100644 index ad3ce8e..0000000 --- a/include/views/osint_dns_review_dialog.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * @file osint_dns_review_dialog.h - * @brief Dialogue de sélection des propositions issues d'une réponse DNS. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_OSINT_DNS_REVIEW_DIALOG_H -#define LABFY_INVESTIGATION_OSINT_DNS_REVIEW_DIALOG_H - -#include - -G_BEGIN_DECLS - -/** - * @brief Callback appelé après confirmation de la sélection DNS. - * - * Le tableau et les propositions sont empruntés et uniquement valides pendant - * l'appel. Le tableau contient seulement les propositions compatibles cochées. - * - * @param selected_proposals Propositions sélectionnées. - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*OsintDnsReviewDialogConfirmCallback)( - GPtrArray *selected_proposals, - gpointer user_data -); - -/** - * @brief Affiche le dialogue de sélection avant intégration. - * - * Le dialogue conserve une référence sur proposals jusqu'à sa fermeture. - * Fermer ou annuler ne déclenche pas le callback. - * - * @param parent_window Fenêtre parente, ou NULL. - * @param proposals Tableau de OsintDnsProposal à réviser. - * @param callback Callback de confirmation facultatif. - * @param user_data Données empruntées transmises au callback. - */ -void osint_dns_review_dialog_present( - GtkWindow *parent_window, - GPtrArray *proposals, - OsintDnsReviewDialogConfirmCallback callback, - gpointer user_data -); - -G_END_DECLS - -#endif diff --git a/include/views/osint_execution_history_dialog.h b/include/views/osint_execution_history_dialog.h deleted file mode 100644 index 44d23b9..0000000 --- a/include/views/osint_execution_history_dialog.h +++ /dev/null @@ -1,32 +0,0 @@ -/****************************************************************************** - * @file osint_execution_history_dialog.h - * @brief Consultation en lecture seule de l'historique OSINT. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_OSINT_EXECUTION_HISTORY_DIALOG_H -#define LABFY_INVESTIGATION_OSINT_EXECUTION_HISTORY_DIALOG_H - -#include - -G_BEGIN_DECLS - -/** - * @brief Affiche les exécutions et leurs objets liés dans une fenêtre modale. - * - * La fonction conserve une référence sur les deux conteneurs jusqu'à la - * fermeture. records contient des OsintExecutionRecord. linked_objects associe - * chaque UUID d'exécution à un GPtrArray de chaînes. - * - * @param parent_window Fenêtre parente, ou NULL. - * @param records Historique non vide, de la plus récente à l'ancienne. - * @param linked_objects Table des objets liés par UUID d'exécution. - */ -void osint_execution_history_dialog_present( - GtkWindow *parent_window, - GPtrArray *records, - GHashTable *linked_objects -); - -G_END_DECLS - -#endif diff --git a/include/views/pdf_password_dialog.h b/include/views/pdf_password_dialog.h deleted file mode 100644 index 2a89cfa..0000000 --- a/include/views/pdf_password_dialog.h +++ /dev/null @@ -1,29 +0,0 @@ -/****************************************************************************** - * @file pdf_password_dialog.h - * @brief Paramétrage d'une récupération de mot de passe PDF. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_PDF_PASSWORD_DIALOG_H -#define LABFY_INVESTIGATION_PDF_PASSWORD_DIALOG_H - -#include "core/pdf_password_recovery.h" -#include - -G_BEGIN_DECLS - -/** @brief Callback recevant la méthode et son paramètre validé. */ -typedef void (*PdfPasswordDialogCallback)(PdfPasswordRecoveryMethod method, - const char *parameter, gpointer user_data); - -/** - * @brief Présente le formulaire de récupération ciblée. - * @param parent Fenêtre parente facultative. - * @param callback Callback appelé après validation. - * @param user_data Données empruntées du callback. - */ -void pdf_password_dialog_present(GtkWindow *parent, - PdfPasswordDialogCallback callback, gpointer user_data); - -G_END_DECLS - -#endif diff --git a/include/views/person_factual_relation_editor.h b/include/views/person_factual_relation_editor.h deleted file mode 100644 index 63f6de6..0000000 --- a/include/views/person_factual_relation_editor.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef LABFY_PERSON_FACTUAL_RELATION_EDITOR_H -#define LABFY_PERSON_FACTUAL_RELATION_EDITOR_H - -#include -#include "core/person_creation_coordinator.h" -#include "models/identity_ocr.h" - -G_BEGIN_DECLS - -typedef struct PersonFactualRelationEditor PersonFactualRelationEditor; - -PersonFactualRelationEditor *person_factual_relation_editor_new(void); - -GtkWidget *person_factual_relation_editor_get_widget( - PersonFactualRelationEditor *editor); - -void person_factual_relation_editor_set_available_evidence( - PersonFactualRelationEditor *editor, - GtkStringList *evidence_labels, - GPtrArray *evidence_identifiers); - -void person_factual_relation_editor_set_available_ocr_runs( - PersonFactualRelationEditor *editor, - GPtrArray *ocr_runs); - -gboolean person_factual_relation_editor_collect_relations( - PersonFactualRelationEditor *editor, GPtrArray **relations, - GError **error); -guint person_factual_relation_editor_get_count( - const PersonFactualRelationEditor *editor); -gboolean person_factual_relation_editor_validate( - PersonFactualRelationEditor *editor, GError **error); -void person_factual_relation_editor_append_summary( - PersonFactualRelationEditor *editor, GString *summary); - -void person_factual_relation_editor_free(PersonFactualRelationEditor *editor); - -G_END_DECLS - -#endif diff --git a/include/views/person_ocr_projection_editor.h b/include/views/person_ocr_projection_editor.h deleted file mode 100644 index 59b5657..0000000 --- a/include/views/person_ocr_projection_editor.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef LABFY_PERSON_OCR_PROJECTION_EDITOR_H -#define LABFY_PERSON_OCR_PROJECTION_EDITOR_H -#include "models/identity_ocr.h" -#include "models/person_ocr_projection.h" -#include -G_BEGIN_DECLS -typedef struct PersonOcrProjectionEditor PersonOcrProjectionEditor; -PersonOcrProjectionEditor *person_ocr_projection_editor_new(void); -GtkWidget *person_ocr_projection_editor_get_widget(PersonOcrProjectionEditor *editor); -void person_ocr_projection_editor_set_runs(PersonOcrProjectionEditor *editor,const GPtrArray *runs); -gboolean person_ocr_projection_editor_collect(PersonOcrProjectionEditor *editor,GPtrArray **projections,GError **error); -void person_ocr_projection_editor_append_summary( - PersonOcrProjectionEditor *editor, GString *summary); -void person_ocr_projection_editor_free(PersonOcrProjectionEditor *editor); -G_END_DECLS -#endif diff --git a/include/views/person_vocabulary_adapter.h b/include/views/person_vocabulary_adapter.h deleted file mode 100644 index 2d35640..0000000 --- a/include/views/person_vocabulary_adapter.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef LABFY_PERSON_VOCABULARY_ADAPTER_H -#define LABFY_PERSON_VOCABULARY_ADAPTER_H -#include "database/database.h" -#include "models/identity_traceability.h" -#include -G_BEGIN_DECLS -typedef struct PersonVocabularyAdapter PersonVocabularyAdapter; -PersonVocabularyAdapter *person_vocabulary_adapter_new( - Database *database, GError **error); -void person_vocabulary_adapter_free(PersonVocabularyAdapter *adapter); -const GPtrArray *person_vocabulary_adapter_get_roles( - const PersonVocabularyAdapter *adapter); -const GPtrArray *person_vocabulary_adapter_get_statuses( - const PersonVocabularyAdapter *adapter); -GtkStringList *person_vocabulary_adapter_create_role_labels( - const PersonVocabularyAdapter *adapter); -GtkStringList *person_vocabulary_adapter_create_status_labels( - const PersonVocabularyAdapter *adapter); -GtkStringList *person_vocabulary_adapter_create_relation_labels(void); -const char *person_vocabulary_adapter_relation_code(guint index); -const char *person_vocabulary_adapter_relation_label(const char *code); -const char *person_vocabulary_adapter_relation_description(const char *code); -const char *person_vocabulary_adapter_status_code( - const PersonVocabularyAdapter *adapter, guint index); -const char *person_vocabulary_adapter_status_label( - const PersonVocabularyAdapter *adapter, guint index); -GPtrArray *person_vocabulary_adapter_selected_role_labels( - const GPtrArray *buttons); -GPtrArray *person_vocabulary_adapter_create_role_buttons( - const PersonVocabularyAdapter *adapter, GtkBox *container); -GPtrArray *person_vocabulary_adapter_build_role_assignments( - const PersonVocabularyAdapter *adapter, const GPtrArray *buttons, - const char *evidence_identifier); -gboolean person_vocabulary_adapter_justification_valid( - const PersonRoleVocabularyEntry *entry, const char *justification); -G_END_DECLS -#endif diff --git a/include/views/rib_ocr_review_dialog.h b/include/views/rib_ocr_review_dialog.h deleted file mode 100644 index 43c67c8..0000000 --- a/include/views/rib_ocr_review_dialog.h +++ /dev/null @@ -1,15 +0,0 @@ -/****************************************************************************** - * @file rib_ocr_review_dialog.h - * @brief Révision humaine des résultats OCR d'un RIB. - ******************************************************************************/ -#ifndef LABFY_INVESTIGATION_RIB_OCR_REVIEW_DIALOG_H -#define LABFY_INVESTIGATION_RIB_OCR_REVIEW_DIALOG_H -#include -G_BEGIN_DECLS -typedef void (*RibOcrReviewCallback)(const char *iban, gpointer user_data); -/** @brief Présente le texte OCR et un IBAN révisable. */ -void rib_ocr_review_dialog_present(GtkWindow *parent, const char *ocr_text, - const char *suggested_iban, RibOcrReviewCallback callback, - gpointer user_data); -G_END_DECLS -#endif diff --git a/include/widgets/controlled_vocab_dropdown.h b/include/widgets/controlled_vocab_dropdown.h deleted file mode 100644 index efeeae3..0000000 --- a/include/widgets/controlled_vocab_dropdown.h +++ /dev/null @@ -1,40 +0,0 @@ -/****************************************************************************** - * @file controlled_vocab_dropdown.h - * @brief Composant GTK4 (GtkDropDown) basé sur le vocabulaire contrôlé. - ******************************************************************************/ -#ifndef LABFY_INVESTIGATION_CONTROLLED_VOCAB_DROPDOWN_H -#define LABFY_INVESTIGATION_CONTROLLED_VOCAB_DROPDOWN_H - -#include "core/controlled_vocab.h" -#include - -G_BEGIN_DECLS - -/** - * @brief Crée un widget GtkDropDown initialisé avec une catégorie de vocabulaire contrôlé. - * @param category Catégorie de vocabulaire. - * @param default_code Code sélectionné par défaut (facultatif). - * @return Nouveau GtkWidget (GtkDropDown). - */ -GtkWidget *controlled_vocab_dropdown_new(ControlledVocabCategory category, - const char *default_code); - -/** - * @brief Obtient le code technique sélectionné dans le dropdown. - * @param dropdown Widget GtkDropDown créé avec controlled_vocab_dropdown_new. - * @return Code technique emprunté, ou NULL si rien n'est sélectionné. - */ -const char *controlled_vocab_dropdown_get_selected_code(GtkWidget *dropdown); - -/** - * @brief Sélectionne un code technique dans le dropdown. - * @param dropdown Widget GtkDropDown. - * @param code Code à sélectionner. - * @return TRUE si le code a été trouvé et sélectionné, FALSE sinon. - */ -gboolean controlled_vocab_dropdown_set_selected_code(GtkWidget *dropdown, - const char *code); - -G_END_DECLS - -#endif /* LABFY_INVESTIGATION_CONTROLLED_VOCAB_DROPDOWN_H */ diff --git a/include/widgets/entity_details_panel.h b/include/widgets/entity_details_panel.h deleted file mode 100644 index 167d65c..0000000 --- a/include/widgets/entity_details_panel.h +++ /dev/null @@ -1,226 +0,0 @@ -/****************************************************************************** - * @file entity_details_panel.h - * @brief Volet latéral affichant les détails d'une entité. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_ENTITY_DETAILS_PANEL_H -#define LABFY_INVESTIGATION_ENTITY_DETAILS_PANEL_H - -#include -#include "models/entity_record.h" - -G_BEGIN_DECLS - -/** - * @brief Modèle opaque représentant une entité. - */ -typedef struct EntityRecord EntityRecord; - -/** - * @brief Représentation opaque du volet de détails. - */ -typedef struct EntityDetailsPanel EntityDetailsPanel; - -/** - * @brief Callback appelé lorsque l'utilisateur ferme le volet. - * - * Le callback n'est pas déclenché lors d'une fermeture programmatique avec - * entity_details_panel_clear(). - * - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*EntityDetailsPanelCloseCallback)( - gpointer user_data -); - -/** - * @brief Callback appelé lorsque l'utilisateur demande une relation. - * - * L'identifiant est emprunté et uniquement valide pendant l'appel. - * - * @param source_entity_identifier UUID de l'entité source. - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*EntityDetailsPanelAddRelationCallback)( - const char *source_entity_identifier, - gpointer user_data -); - -/** @brief Callback appelé lors du changement de catégorie d'une personne. */ -typedef void (*EntityDetailsPanelPersonRoleCallback)( - const char *entity_identifier, - PersonRole role, - gpointer user_data -); - -/** @brief Callback appelé pour enregistrer la confiance d'une personne. */ -typedef void (*EntityDetailsPanelPersonConfidenceCallback)( - const char *entity_identifier, - gint confidence, - gpointer user_data -); - -/** @brief Callback appelé pour enregistrer le nom affiché d'une personne. */ -typedef void (*EntityDetailsPanelPersonNameCallback)( - const char *entity_identifier, - const char *display_name, - gpointer user_data -); -/** @brief Callback appelé pour gérer les preuves d'une personne. */ -typedef void (*EntityDetailsPanelPersonEvidenceCallback)( - const char *entity_identifier, gpointer user_data); -/** @brief Callback appelé lorsqu'une preuve associée est activée. */ -typedef void (*EntityDetailsPanelEvidenceActivatedCallback)( - const char *evidence_identifier, gpointer user_data); -/** @brief Callback appelé pour ouvrir les recherches OSINT compatibles. */ -typedef void (*EntityDetailsPanelOsintCallback)( - const char *entity_identifier, gpointer user_data); - -/** - * @brief Crée un volet de détails fermé. - * - * @return Nouveau volet, ou NULL en cas d'échec. - */ -EntityDetailsPanel *entity_details_panel_new(void); - -/** - * @brief Retourne le widget GTK racine du volet. - * - * Le widget appartient au module EntityDetailsPanel. - * - * @param details_panel Volet à consulter. - * - * @return Widget GTK racine, ou NULL. - */ -GtkWidget *entity_details_panel_get_widget( - const EntityDetailsPanel *details_panel -); - -/** - * @brief Affiche une entité et ouvre le volet. - * - * Les textes sont immédiatement copiés dans les widgets GTK. - * Le pointeur EntityRecord n'est jamais conservé. - * - * Passer NULL équivaut à entity_details_panel_clear(). - * - * @param details_panel Volet à mettre à jour. - * @param entity_record Entité empruntée, ou NULL. - */ -void entity_details_panel_set_entity( - EntityDetailsPanel *details_panel, - const EntityRecord *entity_record -); - -/** - * @brief Vide et referme le volet sans appeler le callback de fermeture. - * - * @param details_panel Volet à vider. - */ -void entity_details_panel_clear( - EntityDetailsPanel *details_panel -); - -/** - * @brief Définit le callback du bouton de fermeture. - * - * Le callback et user_data sont empruntés. - * - * @param details_panel Volet à configurer. - * @param callback Callback à appeler, ou NULL. - * @param user_data Données empruntées du callback. - */ -void entity_details_panel_set_close_callback( - EntityDetailsPanel *details_panel, - EntityDetailsPanelCloseCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback du bouton d'ajout d'une relation. - * - * Le volet transmet uniquement l'UUID de l'entité actuellement affichée. - * - * @param details_panel Volet à configurer. - * @param callback Callback à appeler, ou NULL. - * @param user_data Données empruntées du callback. - */ -void entity_details_panel_set_add_relation_callback( - EntityDetailsPanel *details_panel, - EntityDetailsPanelAddRelationCallback callback, - gpointer user_data -); - -/** @brief Définit le callback de changement de catégorie d'une personne. */ -void entity_details_panel_set_person_role_callback( - EntityDetailsPanel *details_panel, - EntityDetailsPanelPersonRoleCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de modification de la confiance d'une personne. - * - * @param details_panel Volet à configurer. - * @param callback Callback à appeler, ou NULL. - * @param user_data Données empruntées du callback. - */ -void entity_details_panel_set_person_confidence_callback( - EntityDetailsPanel *details_panel, - EntityDetailsPanelPersonConfidenceCallback callback, - gpointer user_data -); - -/** @brief Définit le callback de modification du nom affiché. */ -void entity_details_panel_set_person_name_callback( - EntityDetailsPanel *details_panel, - EntityDetailsPanelPersonNameCallback callback, - gpointer user_data -); -/** @brief Définit le callback de gestion des preuves d'une personne. */ -void entity_details_panel_set_person_evidence_callback( - EntityDetailsPanel *details_panel, - EntityDetailsPanelPersonEvidenceCallback callback, gpointer user_data); -void entity_details_panel_set_evidence_activated_callback( - EntityDetailsPanel *details_panel, - EntityDetailsPanelEvidenceActivatedCallback callback, - gpointer user_data); -/** @brief Définit le callback du bouton de recherche OSINT. */ -void entity_details_panel_set_osint_callback(EntityDetailsPanel *details_panel, - EntityDetailsPanelOsintCallback callback, gpointer user_data); -/** - * @brief Affiche les preuves associées à la personne courante. - * @param details_panel Volet à mettre à jour. - * @param evidence_records Tableau emprunté de EvidenceRecord, ou NULL. - */ -void entity_details_panel_set_person_evidences( - EntityDetailsPanel *details_panel, const GPtrArray *evidence_records); -void entity_details_panel_set_person_factual_relations( - EntityDetailsPanel *details_panel, const GPtrArray *relations, const GPtrArray *evidence_records); -void entity_details_panel_set_person_profile_fields(EntityDetailsPanel *details_panel,const GHashTable *fields); - -/** - * @brief Indique si le volet est actuellement ouvert. - * - * @param details_panel Volet à consulter. - * - * @return TRUE si le volet est ouvert, sinon FALSE. - */ -gboolean entity_details_panel_is_open( - const EntityDetailsPanel *details_panel -); - -/** - * @brief Libère la structure d'encapsulation du volet. - * - * Cette fonction accepte NULL. - * - * @param details_panel Volet à libérer. - */ -void entity_details_panel_free( - EntityDetailsPanel *details_panel -); - -G_END_DECLS - -#endif diff --git a/include/widgets/evidence_preview_widget.h b/include/widgets/evidence_preview_widget.h deleted file mode 100644 index 5852a18..0000000 --- a/include/widgets/evidence_preview_widget.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef LABFY_INVESTIGATION_EVIDENCE_PREVIEW_WIDGET_H -#define LABFY_INVESTIGATION_EVIDENCE_PREVIEW_WIDGET_H - -#include "core/evidence_preview.h" -#include "core/task_manager.h" -#include - -G_BEGIN_DECLS - -typedef struct EvidencePreviewWidget EvidencePreviewWidget; -typedef gboolean (*EvidencePreviewWidgetSessionCheck)(gpointer user_data); - -EvidencePreviewWidget *evidence_preview_widget_new( - TaskManager *task_manager, - EvidencePreviewWidgetSessionCheck session_check, - gpointer session_data); -GtkWidget *evidence_preview_widget_get_widget( - const EvidencePreviewWidget *widget); -void evidence_preview_widget_show(EvidencePreviewWidget *widget, - const EvidencePreviewRequest *request, const char *metadata); -void evidence_preview_widget_clear(EvidencePreviewWidget *widget); -void evidence_preview_widget_cancel(EvidencePreviewWidget *widget); -void evidence_preview_widget_free(EvidencePreviewWidget *widget); -const char *evidence_preview_widget_get_state( - const EvidencePreviewWidget *widget); -char *evidence_preview_widget_dup_text( - const EvidencePreviewWidget *widget); -void evidence_preview_widget_zoom_in(EvidencePreviewWidget *widget); -void evidence_preview_widget_zoom_out(EvidencePreviewWidget *widget); -void evidence_preview_widget_fit(EvidencePreviewWidget *widget); -double evidence_preview_widget_get_zoom( - const EvidencePreviewWidget *widget); -gboolean evidence_preview_widget_is_fit( - const EvidencePreviewWidget *widget); -gboolean evidence_preview_widget_set_pdf_page( - EvidencePreviewWidget *widget, guint page); -guint evidence_preview_widget_get_pdf_page( - const EvidencePreviewWidget *widget); -guint evidence_preview_widget_get_pdf_page_count( - const EvidencePreviewWidget *widget); - -G_END_DECLS -#endif diff --git a/include/widgets/evidence_tree_view.h b/include/widgets/evidence_tree_view.h deleted file mode 100644 index 1e81db4..0000000 --- a/include/widgets/evidence_tree_view.h +++ /dev/null @@ -1,99 +0,0 @@ -/****************************************************************************** - * @file evidence_tree_view.h - * @brief Affichage GTK hiérarchique des catégories et preuves importées. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_EVIDENCE_TREE_VIEW_H -#define LABFY_INVESTIGATION_EVIDENCE_TREE_VIEW_H - -#include "widgets/evidence_category_model.h" - -#include - -G_BEGIN_DECLS - -/** - * @brief Vue opaque affichant les preuves regroupées par catégorie. - */ -typedef struct EvidenceTreeView EvidenceTreeView; - -/** - * @brief Callback appelé lorsqu'une preuve est sélectionnée. - * - * L'identifiant est emprunté et uniquement valide pendant l'appel. - * - * Lorsque la sélection est vide ou correspond à une catégorie, - * evidence_identifier vaut NULL. - * - * @param evidence_identifier UUID de la preuve sélectionnée, ou NULL. - * @param user_data Données privées fournies par l'appelant. - */ -typedef void (*EvidenceTreeViewSelectionCallback)( - const char *evidence_identifier, - gpointer user_data -); - -/** - * @brief Crée une vue hiérarchique vide. - * - * @return Nouvelle vue, ou NULL. - */ -EvidenceTreeView *evidence_tree_view_new(void); - -/** - * @brief Retourne le widget GTK racine. - * - * Le widget retourné est emprunté. - * - * @param evidence_tree_view Vue à consulter. - * - * @return GtkScrolledWindow racine, ou NULL. - */ -GtkWidget *evidence_tree_view_get_widget( - const EvidenceTreeView *evidence_tree_view -); - -/** - * @brief Installe un modèle de catégories. - * - * La vue ne devient pas propriétaire de EvidenceCategoryModel. - * Le modèle doit rester valide pendant son utilisation. - * - * Passer NULL vide la vue. - * - * @param evidence_tree_view Vue à actualiser. - * @param evidence_category_model Modèle de catégories, ou NULL. - */ -void evidence_tree_view_set_model( - EvidenceTreeView *evidence_tree_view, - EvidenceCategoryModel *evidence_category_model -); - -/** - * @brief Définit le callback de sélection. - * - * @param evidence_tree_view Vue à configurer. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void evidence_tree_view_set_selection_callback( - EvidenceTreeView *evidence_tree_view, - EvidenceTreeViewSelectionCallback callback, - gpointer user_data -); - -/** - * @brief Libère la structure d'encapsulation. - * - * Les widgets GTK intégrés dans la fenêtre restent gérés par l'arbre GTK. - * Cette fonction accepte NULL. - * - * @param evidence_tree_view Vue à libérer. - */ -void evidence_tree_view_free( - EvidenceTreeView *evidence_tree_view -); - -G_END_DECLS - -#endif diff --git a/include/widgets/investigation_graph_view.h b/include/widgets/investigation_graph_view.h deleted file mode 100644 index ae316e4..0000000 --- a/include/widgets/investigation_graph_view.h +++ /dev/null @@ -1,304 +0,0 @@ -/****************************************************************************** - * @file investigation_graph_view.h - * @brief Vue GTK en lecture seule du graphe d'enquête. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_INVESTIGATION_GRAPH_VIEW_H -#define LABFY_INVESTIGATION_INVESTIGATION_GRAPH_VIEW_H - -#include - -G_BEGIN_DECLS - -/** - * @brief Représentation opaque d'une entité métier. - */ -typedef struct EntityRecord EntityRecord; - -/** - * @brief Représentation opaque d'une relation métier. - */ -typedef struct RelationRecord RelationRecord; - -/** - * @brief Représentation opaque du graphe métier d'une enquête. - */ -typedef struct InvestigationGraphModel InvestigationGraphModel; - -/** - * @brief Représentation opaque de la disposition persistée du graphe. - */ -typedef struct InvestigationGraphLayout InvestigationGraphLayout; - -/** - * @brief Représentation opaque de la vue graphique. - */ -typedef struct InvestigationGraphView InvestigationGraphView; - -/** - * @brief Callback appelé lors d'un changement de sélection. - * - * Les enregistrements sont empruntés au graphe et restent valides uniquement - * pendant l'appel. Un seul des deux pointeurs est non NULL. Deux pointeurs - * NULL représentent une désélection. - * - * @param entity_record Entité sélectionnée empruntée, ou NULL. - * @param relation_record Relation sélectionnée empruntée, ou NULL. - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*InvestigationGraphViewSelectionCallback)( - const EntityRecord *entity_record, - const RelationRecord *relation_record, - gpointer user_data -); - -/** - * @brief Callback appelé après le déplacement effectif d'un nœud. - * - * Les coordonnées sont exprimées dans l'espace logique du graphe. - * node_identifier est emprunté au modèle et reste valable uniquement - * pendant l'appel. - * - * @param node_identifier UUID du nœud déplacé (entité ou relation). - * @param x Coordonnée horizontale logique du coin supérieur gauche. - * @param y Coordonnée verticale logique du coin supérieur gauche. - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*InvestigationGraphViewNodeMovedCallback)( - const char *node_identifier, - double x, - double y, - gpointer user_data -); - -typedef void (*InvestigationGraphViewTransformChangedCallback)( - gpointer user_data -); - -/** @brief Callback appelé lorsqu'une extraction est déposée sur le graphe. */ -typedef void (*InvestigationGraphViewExtractionDropCallback)( - const char *file_path, - const char *target_entity_identifier, - gpointer user_data -); - -/** - * @brief Crée une nouvelle vue graphique vide. - * - * La vue ne possède jamais le graphe qui lui est transmis. - * - * @return Nouvelle vue graphique, ou NULL en cas d'échec. - */ -InvestigationGraphView *investigation_graph_view_new(void); - -/** - * @brief Retourne le widget GTK racine de la vue. - * - * Le widget appartient à InvestigationGraphView. - * - * @param graph_view Vue graphique à consulter. - * - * @return Widget GTK racine, ou NULL. - */ -GtkWidget *investigation_graph_view_get_widget( - const InvestigationGraphView *graph_view -); - -/** - * @brief Associe un graphe métier à la vue. - * - * Le graphe est emprunté et doit rester valide pendant son affichage. - * Passer NULL équivaut à investigation_graph_view_clear(). - * - * @param graph_view Vue graphique à mettre à jour. - * @param graph_model Graphe emprunté, ou NULL. - */ -void investigation_graph_view_set_graph( - InvestigationGraphView *graph_view, - const InvestigationGraphModel *graph_model -); - -/** - * @brief Associe une disposition persistée à la vue. - * - * La disposition est empruntée et doit rester valide pendant son utilisation. - * - * Lorsqu'un graphe est déjà affiché, la disposition privée de ses nœuds est - * reconstruite. Une position persistée remplace la position automatique - * uniquement lorsqu'elle existe pour l'entité concernée. - * - * Passer NULL rétablit le placement automatique. - * - * @param graph_view Vue graphique à mettre à jour. - * @param graph_layout Disposition persistée empruntée, ou NULL. - */ -void investigation_graph_view_set_layout( - InvestigationGraphView *graph_view, - const InvestigationGraphLayout *graph_layout -); - -/** - * @brief Détache le graphe actuellement affiché. - * - * Le graphe précédemment emprunté n'est pas libéré. - * - * @param graph_view Vue graphique à vider. - */ -void investigation_graph_view_clear( - InvestigationGraphView *graph_view -); - -/** - * @brief Définit le callback de changement de sélection. - * - * Le callback et user_data sont empruntés par la vue. - * - * @param graph_view Vue graphique. - * @param callback Callback à appeler, ou NULL. - * @param user_data Données empruntées du callback. - */ -void investigation_graph_view_set_selection_callback( - InvestigationGraphView *graph_view, - InvestigationGraphViewSelectionCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de fin de déplacement d'un nœud. - * - * Le callback et user_data sont empruntés par la vue. - * - * Le callback n'est appelé ni pendant le déplacement du canvas, ni pour - * un simple clic, ni pendant une reconstruction de la disposition. - * - * @param graph_view Vue graphique. - * @param callback Callback à appeler, ou NULL. - * @param user_data Données empruntées du callback. - */ -void investigation_graph_view_set_node_moved_callback( - InvestigationGraphView *graph_view, - InvestigationGraphViewNodeMovedCallback callback, - gpointer user_data -); - -void investigation_graph_view_set_transform_changed_callback( - InvestigationGraphView *graph_view, - InvestigationGraphViewTransformChangedCallback callback, - gpointer user_data -); - -void investigation_graph_view_set_extraction_drop_callback( - InvestigationGraphView *graph_view, - InvestigationGraphViewExtractionDropCallback callback, - gpointer user_data -); - -/** - * @brief Retourne l'entité actuellement sélectionnée. - * - * Le pointeur retourné est emprunté au graphe. - * - * @param graph_view Vue graphique à consulter. - * - * @return Entité sélectionnée empruntée, ou NULL. - */ -const EntityRecord *investigation_graph_view_get_selected_entity( - const InvestigationGraphView *graph_view -); - -/** - * @brief Sélectionne une entité du graphe par son UUID. - * - * Le nœud trouvé est placé au centre de la zone visible. La vue reste - * inchangée si l'identifiant est absent du graphe. - * - * @param graph_view Vue graphique à modifier. - * @param entity_identifier UUID de l'entité. - * - * @return TRUE lorsque l'entité est trouvée et sélectionnée. - */ -gboolean investigation_graph_view_select_entity( - InvestigationGraphView *graph_view, - const char *entity_identifier -); - -/** - * @brief Sélectionne une relation du graphe par son UUID. - * - * @param graph_view Vue graphique à modifier. - * @param relation_identifier UUID de la relation. - * - * @return TRUE lorsque la relation est trouvée et sélectionnée. - */ -gboolean investigation_graph_view_select_relation( - InvestigationGraphView *graph_view, - const char *relation_identifier -); - -/** - * @brief Supprime la sélection courante. - * - * Le callback reçoit NULL seulement si une sélection existait. - * - * @param graph_view Vue graphique. - */ -void investigation_graph_view_clear_selection( - InvestigationGraphView *graph_view -); - -/** - * @brief Réinitialise le zoom et la position du canvas. - * - * Le graphe emprunté reste associé à la vue. - * - * @param graph_view Vue graphique à recentrer. - */ -void investigation_graph_view_reset_view( - InvestigationGraphView *graph_view -); - -/** - * @brief Lit le zoom et le déplacement courants du canvas. - * - * @return TRUE lorsqu'un graphe est actuellement présenté. - */ -gboolean investigation_graph_view_get_view_transform( - const InvestigationGraphView *graph_view, - double *zoom, - double *offset_x, - double *offset_y -); - -/** @brief Restaure un zoom et un déplacement précédemment lus. */ -void investigation_graph_view_set_view_transform( - InvestigationGraphView *graph_view, - double zoom, - double offset_x, - double offset_y -); - -/** - * @brief Restaure la disposition déterministe initiale des nœuds. - * - * Le zoom et le déplacement global du canvas sont conservés. - * - * @param graph_view Vue graphique à réorganiser. - */ -void investigation_graph_view_reset_layout( - InvestigationGraphView *graph_view -); - -/** - * @brief Libère la structure d'encapsulation de la vue. - * - * Cette fonction accepte NULL et ne libère jamais le graphe emprunté. - * - * @param graph_view Vue graphique à libérer. - */ -void investigation_graph_view_free( - InvestigationGraphView *graph_view -); - -G_END_DECLS - -#endif diff --git a/include/widgets/investigation_tree_view.h b/include/widgets/investigation_tree_view.h deleted file mode 100644 index c39649a..0000000 --- a/include/widgets/investigation_tree_view.h +++ /dev/null @@ -1,103 +0,0 @@ -/****************************************************************************** - * @file investigation_tree_view.h - * @brief Interface publique de la vue arborescente d'une enquête. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_INVESTIGATION_TREE_VIEW_H -#define LABFY_INVESTIGATION_INVESTIGATION_TREE_VIEW_H - -#include "core/investigation_tree_model.h" - -#include - -/** - * @brief Représentation opaque de la vue arborescente d'une enquête. - * - * La structure réelle est définie dans investigation_tree_view.c. - * Les autres modules manipulent uniquement un pointeur vers - * InvestigationTreeView. - */ -typedef struct InvestigationTreeView InvestigationTreeView; - -/** - * @brief Callback appelé lorsqu'un nœud est sélectionné. - * - * @param node Nœud sélectionné, ou NULL si aucune sélection n'est active. - * @param user_data Données privées fournies lors de l'enregistrement - * du callback. - */ -typedef void (*InvestigationTreeViewSelectionCallback)( - const InvestigationNode *node, - gpointer user_data -); - -/** - * @brief Définit le callback de sélection. - * - * Le callback est appelé à chaque changement de sélection. - * - * Le composant ne devient pas propriétaire du callback ni de user_data. - * - * @param tree_view Vue arborescente. - * @param callback Fonction appelée lors d'une sélection. - * @param user_data Données privées transmises au callback. - */ -void investigation_tree_view_set_selection_callback( - InvestigationTreeView *tree_view, - InvestigationTreeViewSelectionCallback callback, - gpointer user_data -); - -/** - * @brief Crée une nouvelle vue arborescente vide. - * - * Aucun modèle métier n'est associé au composant lors de sa création. - * - * @return Une nouvelle vue, ou NULL si sa création échoue. - */ -InvestigationTreeView *investigation_tree_view_new(void); - -/** - * @brief Retourne le widget GTK racine de la vue arborescente. - * - * Le widget retourné appartient au module InvestigationTreeView. - * Le code appelant ne doit ni le détruire ni en libérer la référence. - * - * @param tree_view Vue arborescente à consulter. - * - * @return Le widget racine, ou NULL si tree_view vaut NULL. - */ -GtkWidget *investigation_tree_view_get_widget( - const InvestigationTreeView *tree_view -); - -/** - * @brief Associe un modèle métier à la vue arborescente. - * - * La vue ne devient pas propriétaire du modèle. Le modèle doit rester valide - * pendant toute la durée de son affichage. - * - * Passer NULL retire le modèle actuel et vide la vue. - * - * @param tree_view Vue arborescente à mettre à jour. - * @param tree_model Modèle métier en lecture seule, ou NULL. - */ -void investigation_tree_view_set_model( - InvestigationTreeView *tree_view, - const InvestigationTreeModel *tree_model -); - -/** - * @brief Libère la structure d'encapsulation de la vue. - * - * Cette fonction accepte NULL. - * - * Les objets GTK intégrés à l'arbre de widgets restent gérés par GTK. - * - * @param tree_view Vue arborescente à libérer. - */ -void investigation_tree_view_free( - InvestigationTreeView *tree_view -); - -#endif diff --git a/include/widgets/ocr_provenance_overlay.h b/include/widgets/ocr_provenance_overlay.h deleted file mode 100644 index f7756f5..0000000 --- a/include/widgets/ocr_provenance_overlay.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef LABFY_OCR_PROVENANCE_OVERLAY_H -#define LABFY_OCR_PROVENANCE_OVERLAY_H - -#include "models/identity_ocr.h" -#include - -typedef struct OcrProvenanceOverlay OcrProvenanceOverlay; - -OcrProvenanceOverlay *ocr_provenance_overlay_new(void); -void ocr_provenance_overlay_free(OcrProvenanceOverlay *overlay); -GtkWidget *ocr_provenance_overlay_get_widget(OcrProvenanceOverlay *overlay); -void ocr_provenance_overlay_set_image(OcrProvenanceOverlay *overlay, - GBytes *png_bytes, guint64 generation); -void ocr_provenance_overlay_set_field(OcrProvenanceOverlay *overlay, - const IdentityFieldObservation *field, guint64 generation); -void ocr_provenance_overlay_clear(OcrProvenanceOverlay *overlay, - guint64 generation); -void ocr_provenance_overlay_set_page( - OcrProvenanceOverlay *overlay, guint page, guint64 generation); -void ocr_provenance_overlay_zoom_in(OcrProvenanceOverlay *overlay); -void ocr_provenance_overlay_zoom_out(OcrProvenanceOverlay *overlay); -void ocr_provenance_overlay_fit(OcrProvenanceOverlay *overlay); -double ocr_provenance_overlay_get_zoom( - const OcrProvenanceOverlay *overlay); -gboolean ocr_provenance_overlay_has_region( - const OcrProvenanceOverlay *overlay); - -#endif diff --git a/include/widgets/sidebar.h b/include/widgets/sidebar.h deleted file mode 100644 index ab1e07f..0000000 --- a/include/widgets/sidebar.h +++ /dev/null @@ -1,190 +0,0 @@ -/****************************************************************************** - * @file sidebar.h - * @brief Interface publique du panneau de navigation latéral. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_SIDEBAR_H -#define LABFY_INVESTIGATION_SIDEBAR_H - -#include "core/investigation_tree_model.h" -#include "widgets/investigation_tree_view.h" -#include "widgets/evidence_category_model.h" -#include "models/investigation_graph_model.h" - -#include - -/** - * @brief Représentation opaque du panneau latéral. - * - * La structure réelle est définie dans sidebar.c. - * Les autres modules manipulent uniquement un pointeur vers Sidebar. - */ -typedef struct Sidebar Sidebar; - -/** - * @brief Callback appelé lorsqu'une preuve est sélectionnée. - * - * L'identifiant est emprunté et uniquement valide pendant l'appel. - * Une sélection vide ou une catégorie transmet NULL. - * - * @param evidence_identifier UUID de la preuve, ou NULL. - * @param user_data Données privées fournies par l'appelant. - */ -typedef void (*SidebarEvidenceSelectionCallback)( - const char *evidence_identifier, - gpointer user_data -); - -/** - * @brief Callback appelé lorsqu'une entité est sélectionnée. - * - * L'identifiant est emprunté et valide uniquement pendant l'appel. - * Une sélection vide transmet NULL. - * - * @param entity_identifier UUID de l'entité, ou NULL. - * @param user_data Données privées fournies par l'appelant. - */ -typedef void (*SidebarEntitySelectionCallback)( - const char *entity_identifier, - gpointer user_data -); - -/** - * @brief Callback appelé lorsqu'une relation est sélectionnée. - * - * @param relation_identifier UUID emprunté de la relation, ou NULL. - * @param user_data Données privées fournies par l'appelant. - */ -typedef void (*SidebarRelationSelectionCallback)( - const char *relation_identifier, - gpointer user_data -); - -/** - * @brief Crée un nouveau panneau de navigation latéral. - * - * @return Un nouveau panneau latéral, ou NULL en cas d'échec. - */ -Sidebar *sidebar_new(void); - -/** - * @brief Retourne le widget GTK racine du panneau latéral. - * - * Le widget retourné appartient au module Sidebar et ne doit pas être libéré - * directement par le code appelant. - * - * @param sidebar Panneau latéral à consulter. - * - * @return Le widget GTK racine, ou NULL si sidebar est NULL. - */ -GtkWidget *sidebar_get_widget( - const Sidebar *sidebar -); - -/** - * @brief Associe un modèle d'arborescence à la barre latérale. - * - * La barre latérale ne devient pas propriétaire du modèle. - * Le modèle doit rester valide pendant toute la durée de son utilisation. - * - * Pour ce ticket, seul le nom du nœud racine est affiché dans le titre. - * - * @param sidebar Barre latérale à mettre à jour. - * @param tree_model Modèle d'arborescence en lecture seule. - */ -void sidebar_set_tree_model( - Sidebar *sidebar, - const InvestigationTreeModel *tree_model -); - -/** - * @brief Définit le callback appelé lors de la sélection d'un nœud. - * - * La Sidebar transmet simplement ce callback à InvestigationTreeView. - * - * @param sidebar Barre latérale à configurer. - * @param callback Fonction appelée lors d'un changement de sélection. - * @param user_data Données privées transmises au callback. - */ -void sidebar_set_selection_callback( - Sidebar *sidebar, - InvestigationTreeViewSelectionCallback callback, - gpointer user_data -); - -/** - * @brief Installe le modèle des catégories de preuves. - * - * La Sidebar ne devient pas propriétaire du modèle. - * Passer NULL rétablit l'état vide. - * - * @param sidebar Barre latérale à actualiser. - * @param evidence_category_model Modèle de catégories, ou NULL. - */ -void sidebar_set_evidence_model( - Sidebar *sidebar, - EvidenceCategoryModel *evidence_category_model -); - -/** - * @brief Définit le callback de sélection d'une preuve. - * - * @param sidebar Barre latérale à configurer. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void sidebar_set_evidence_selection_callback( - Sidebar *sidebar, - SidebarEvidenceSelectionCallback callback, - gpointer user_data -); - -/** - * @brief Installe les entités et relations du graphe dans la barre latérale. - * - * La Sidebar emprunte graph_model. Passer NULL vide la liste. - * - * @param sidebar Barre latérale à actualiser. - * @param graph_model Graphe emprunté, ou NULL. - */ -void sidebar_set_graph_model( - Sidebar *sidebar, - const InvestigationGraphModel *graph_model -); - -/** - * @brief Définit le callback de sélection d'une entité. - * - * @param sidebar Barre latérale à configurer. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void sidebar_set_entity_selection_callback( - Sidebar *sidebar, - SidebarEntitySelectionCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de sélection d'une relation. - * - * @param sidebar Barre latérale à configurer. - * @param callback Callback facultatif. - * @param user_data Données privées transmises au callback. - */ -void sidebar_set_relation_selection_callback( - Sidebar *sidebar, - SidebarRelationSelectionCallback callback, - gpointer user_data -); - -/** - * @brief Libère la structure d'encapsulation du panneau latéral. - * - * Cette fonction accepte NULL. - * - * @param sidebar Panneau latéral à libérer. - */ -void sidebar_free(Sidebar *sidebar); - -#endif diff --git a/include/widgets/task_panel.h b/include/widgets/task_panel.h deleted file mode 100644 index 3f07317..0000000 --- a/include/widgets/task_panel.h +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - * @file task_panel.h - * @brief Panneau GTK affichant les tâches suivies par TaskManager. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_TASK_PANEL_H -#define LABFY_INVESTIGATION_TASK_PANEL_H - -#include "core/task_manager.h" - -#include - -/** - * @brief Représentation opaque du panneau d’activité. - */ -typedef struct TaskPanel TaskPanel; - -/** - * @brief Crée un panneau affichant les tâches d’un gestionnaire. - * - * Le panneau ne devient pas propriétaire de task_manager. - * Le gestionnaire doit rester valide pendant toute la durée de vie - * du panneau. - * - * @param task_manager Gestionnaire de tâches observé. - * - * @return Nouveau panneau, ou NULL si le gestionnaire est invalide. - */ -TaskPanel *task_panel_new( - TaskManager *task_manager -); - -/** - * @brief Retourne le widget racine du panneau. - * - * Le pointeur retourné est emprunté. - * - * @param task_panel Panneau concerné. - * - * @return Widget racine, ou NULL. - */ -GtkWidget *task_panel_get_widget( - const TaskPanel *task_panel -); - -/** - * @brief Reconstruit l’affichage à partir du gestionnaire. - * - * @param task_panel Panneau à actualiser. - */ -void task_panel_refresh( - TaskPanel *task_panel -); - -/** - * @brief Libère le panneau et arrête son rafraîchissement périodique. - * - * Le gestionnaire associé n’est pas libéré. - * - * @param task_panel Panneau à libérer. - */ -void task_panel_free( - TaskPanel *task_panel -); - -#endif diff --git a/include/widgets/workspace.h b/include/widgets/workspace.h deleted file mode 100644 index 366359e..0000000 --- a/include/widgets/workspace.h +++ /dev/null @@ -1,552 +0,0 @@ -/****************************************************************************** - * @file workspace.h - * @brief Interface publique de la zone principale de travail. - ******************************************************************************/ - -#ifndef LABFY_INVESTIGATION_WORKSPACE_H -#define LABFY_INVESTIGATION_WORKSPACE_H - -#include "core/investigation_node.h" -#include "models/evidence_record.h" -#include "models/evidence_observation.h" -#include "models/entity_record.h" -#include "models/osint_action_catalog.h" -#include "models/identity_ocr.h" -#include "core/task_manager.h" - -#include - -/** - * @brief Représentation opaque du graphe d'enquête. - */ -typedef struct InvestigationGraphModel InvestigationGraphModel; - -/** - * @brief Représentation opaque de la disposition du graphe. - */ -typedef struct InvestigationGraphLayout InvestigationGraphLayout; - -/** - * @brief Représentation opaque de la zone de travail. - */ -typedef struct Workspace Workspace; - -/** - * @brief Callback appelé lors d'une demande de vérification d'une preuve. - * - * @param evidence_identifier UUID de la preuve affichée. - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*WorkspaceVerifyEvidenceCallback)( - const char *evidence_identifier, - gpointer user_data -); - -/** - * @brief Callback appelé après le déplacement effectif d'un nœud. - * - * Les coordonnées sont exprimées dans l'espace logique du graphe. - * - * @param node_identifier UUID du nœud déplacé. - * @param x Coordonnée horizontale logique. - * @param y Coordonnée verticale logique. - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*WorkspaceGraphNodeMovedCallback)( - const char *node_identifier, - double x, - double y, - gpointer user_data -); -typedef void (*WorkspaceGraphTransformChangedCallback)(gpointer user_data); - -typedef void (*WorkspaceExtractionDropCallback)( - const char *file_path, - const char *target_entity_identifier, - gpointer user_data -); - -/** - * @brief Callback appelé lors d'une demande de réinitialisation du graphe. - * - * Le Workspace ne modifie ni SQLite ni le modèle de disposition. Il relaie - * uniquement la demande vers la couche applicative. - * - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*WorkspaceResetGraphLayoutCallback)( - gpointer user_data -); - -/** - * @brief Callback appelé lors d'une demande d'ajout d'une relation. - * - * @param source_entity_identifier UUID de l'entité source. - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*WorkspaceAddRelationCallback)( - const char *source_entity_identifier, - gpointer user_data -); - -/** @brief Callback appelé pour modifier la relation sélectionnée. */ -typedef void (*WorkspaceEditRelationCallback)( - const char *relation_identifier, - gpointer user_data -); -/** @brief Callback appelé pour supprimer la relation sélectionnée. */ -typedef void (*WorkspaceDeleteRelationCallback)( - const char *relation_identifier, gpointer user_data); - -/** @brief Callback appelé quand une relation devient sélectionnée. */ -typedef void (*WorkspaceRelationSelectedCallback)( - const char *relation_identifier, - gpointer user_data -); - -/** @brief Callback appelé pour catégoriser une personne. */ -typedef void (*WorkspacePersonRoleCallback)(const char *entity_identifier, - PersonRole role, gpointer user_data); -/** @brief Callback appelé pour modifier la confiance d'une personne. */ -typedef void (*WorkspacePersonConfidenceCallback)( - const char *entity_identifier, gint confidence, gpointer user_data); - -/** - * @brief Callback appelé lors du déclenchement d'une action OSINT. - * - * Les chaînes sont empruntées et uniquement valides pendant l'appel. - * - * @param action_identifier Identifiant stable de l'action. - * @param target_identifier UUID de la sélection ciblée. - * @param target_value Valeur métier ciblée par l'action. - * @param user_data Données empruntées fournies par l'appelant. - */ -typedef void (*WorkspaceOsintActionCallback)( - const char *action_identifier, - const char *target_identifier, - const char *target_value, - gpointer user_data -); -/** @brief Callback appelé pour modifier le nom affiché d'une personne. */ -typedef void (*WorkspacePersonNameCallback)(const char *entity_identifier, - const char *display_name, gpointer user_data); -/** @brief Callback appelé pour gérer les preuves d'une personne. */ -typedef void (*WorkspacePersonEvidenceCallback)( - const char *entity_identifier, gpointer user_data); -typedef void (*WorkspaceEvidenceActivatedCallback)( - const char *evidence_identifier, gpointer user_data); -/** @brief Callback appelé quand une entité devient sélectionnée. */ -typedef void (*WorkspaceEntitySelectedCallback)( - const char *entity_identifier, gpointer user_data); - -/** @brief Callback appelé pour modifier les métadonnées d'une preuve. */ -typedef void (*WorkspaceEditEvidenceCallback)( - const char *evidence_identifier, - gpointer user_data -); -/** @brief Callback appelé pour analyser une preuve EML. */ -typedef void (*WorkspaceAnalyzeEmlCallback)(const char *evidence_identifier, - gpointer user_data); -/** @brief Callback appelé pour analyser un RIB par OCR. */ -typedef void (*WorkspaceAnalyzeRibCallback)(const char *evidence_identifier, - gpointer user_data); -/** @brief Callback appelé pour extraire les métadonnées d'une preuve. */ -typedef void (*WorkspaceExtractMetadataCallback)(const char *evidence_identifier, - gpointer user_data); -/** @brief Callback appelé pour récupérer le mot de passe d'un PDF. */ -typedef void (*WorkspaceRecoverPdfPasswordCallback)( - const char *evidence_identifier, gpointer user_data); -typedef void (*WorkspaceObservationRemoveCallback)( - const char *observation_identifier, gpointer user_data); -typedef void (*WorkspaceIdentityOcrCallback)( - const char *evidence_identifier, gboolean revise_existing, - const char *ocr_run_identifier, gpointer user_data); - -typedef struct { - IdentityOcrRun *run; - char *person_identifier; - char *executed_at; - char *text_relative_path; - char *text_sha256; - char *tsv_relative_path; - char *tsv_sha256; -} WorkspaceIdentityOcrRecord; - -WorkspaceIdentityOcrRecord *workspace_identity_ocr_record_new( - IdentityOcrRun *owned_run, const char *person_identifier, - const char *executed_at, const char *text_relative_path, - const char *text_sha256, const char *tsv_relative_path, - const char *tsv_sha256); -void workspace_identity_ocr_record_free(WorkspaceIdentityOcrRecord *record); - -/** - * @brief Crée une nouvelle zone de travail. - * - * @return Une nouvelle zone de travail, ou NULL en cas d'échec. - */ -Workspace *workspace_new(TaskManager *task_manager); - -/** - * @brief Retourne le widget GTK racine de la zone de travail. - * - * Le widget retourné appartient au module Workspace. - * - * @param workspace Zone de travail à consulter. - * - * @return Widget racine, ou NULL. - */ -GtkWidget *workspace_get_widget( - const Workspace *workspace -); - -/** - * @brief Affiche les informations d'un nœud sélectionné. - * - * Le Workspace emprunte le nœud. - * Passer NULL restaure l'état principal courant. - * - * @param workspace Zone de travail. - * @param node Nœud emprunté, ou NULL. - */ -void workspace_set_selected_node( - Workspace *workspace, - const InvestigationNode *node -); - -/** - * @brief Affiche la fiche détaillée d'une preuve. - * - * Les textes sont copiés dans les widgets. Le Workspace ne conserve pas le - * pointeur EvidenceRecord. - * - * Passer NULL restaure l'état principal courant. - * - * @param workspace Zone de travail. - * @param evidence_record Preuve empruntée, ou NULL. - */ -void workspace_set_selected_evidence( - Workspace *workspace, - const EvidenceRecord *evidence_record -); -void workspace_set_identity_ocr_runs( - Workspace *workspace, GPtrArray *owned_records); -void workspace_set_identity_ocr_callback( - Workspace *workspace, WorkspaceIdentityOcrCallback callback, - gpointer user_data); -void workspace_set_evidence_observations(Workspace *workspace, - const GPtrArray *observations); -void workspace_set_observation_remove_callback(Workspace *workspace, - WorkspaceObservationRemoveCallback callback, gpointer user_data); -void workspace_set_eml_analysis_available( - Workspace *workspace, - gboolean available -); - -/** - * @brief Affiche l'aperçu local d'un fichier image ou vidéo. - * - * file_path doit être un chemin absolu déjà validé par l'application. - * Passer NULL libère l'aperçu courant. - */ -void workspace_set_evidence_preview(Workspace *workspace, - const char *file_path, const char *display_name); -void workspace_show_evidence_preview(Workspace *workspace, - const char *investigation_root, const EvidenceRecord *record); - -/** - * @brief Sélectionne une entité dans le graphe affiché. - * - * La sélection actualise également le volet de détails et le contexte OSINT. - * - * @param workspace Zone de travail. - * @param entity_identifier UUID de l'entité à sélectionner. - * - * @return TRUE lorsque l'entité est trouvée et sélectionnée. - */ -gboolean workspace_select_graph_entity( - Workspace *workspace, - const char *entity_identifier -); - -/** - * @brief Sélectionne une relation dans le graphe affiché. - * - * @param workspace Zone de travail. - * @param relation_identifier UUID de la relation à sélectionner. - * - * @return TRUE lorsque la relation est trouvée et sélectionnée. - */ -gboolean workspace_select_graph_relation( - Workspace *workspace, - const char *relation_identifier -); - -/** - * @brief Actualise l'état d'un outil requis par les actions OSINT. - * - * @param workspace Zone de travail. - * @param tool_identifier Identifiant stable de l'outil. - * @param state État traduit par la couche applicative. - * @param version Version détectée facultative. - */ -void workspace_set_osint_tool_state( - Workspace *workspace, - const char *tool_identifier, - OsintActionToolState state, - const char *version -); - -/** - * @brief Définit le callback de déclenchement des actions OSINT. - * - * Le Workspace ne lance aucun outil externe. Il relaie uniquement l'action - * et la valeur du contexte courant vers la couche applicative. - * - * @param workspace Zone de travail. - * @param callback Callback facultatif. - * @param user_data Données empruntées transmises au callback. - */ -void workspace_set_osint_action_callback( - Workspace *workspace, - WorkspaceOsintActionCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de modification de la preuve sélectionnée. - * @param workspace Zone de travail. - * @param callback Callback facultatif. - * @param user_data Données empruntées transmises au callback. - */ -void workspace_set_edit_evidence_callback( - Workspace *workspace, - WorkspaceEditEvidenceCallback callback, - gpointer user_data -); -/** @brief Définit le callback d'analyse locale d'une preuve EML. */ -void workspace_set_analyze_eml_callback(Workspace *workspace, - WorkspaceAnalyzeEmlCallback callback, gpointer user_data); -/** @brief Définit le callback d'analyse OCR d'un RIB. */ -void workspace_set_analyze_rib_callback(Workspace *workspace, - WorkspaceAnalyzeRibCallback callback, gpointer user_data); -/** @brief Définit le callback d'extraction locale des métadonnées. */ -void workspace_set_extract_metadata_callback(Workspace *workspace, - WorkspaceExtractMetadataCallback callback, gpointer user_data); -/** @brief Définit le callback de récupération d'un mot de passe PDF. */ -void workspace_set_recover_pdf_password_callback(Workspace *workspace, - WorkspaceRecoverPdfPasswordCallback callback, gpointer user_data); - -/** - * @brief Définit le callback de vérification de la preuve affichée. - * - * Le Workspace emprunte callback et user_data. - * - * @param workspace Zone de travail. - * @param callback Callback à utiliser, ou NULL. - * @param user_data Données empruntées du callback. - */ -void workspace_set_verify_evidence_callback( - Workspace *workspace, - WorkspaceVerifyEvidenceCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de fin de déplacement d'un nœud. - * - * Le Workspace relaie uniquement l'événement provenant de la vue graphique. - * - * @param workspace Zone de travail. - * @param callback Callback facultatif. - * @param user_data Données empruntées transmises au callback. - */ -void workspace_set_graph_node_moved_callback( - Workspace *workspace, - WorkspaceGraphNodeMovedCallback callback, - gpointer user_data -); -void workspace_set_graph_transform_changed_callback( - Workspace *workspace, - WorkspaceGraphTransformChangedCallback callback, - gpointer user_data); - -void workspace_set_extraction_drop_callback( - Workspace *workspace, - WorkspaceExtractionDropCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de demande de réinitialisation du graphe. - * - * Le Workspace emprunte callback et user_data. - * - * @param workspace Zone de travail. - * @param callback Callback facultatif. - * @param user_data Données empruntées transmises au callback. - */ -void workspace_set_reset_graph_layout_callback( - Workspace *workspace, - WorkspaceResetGraphLayoutCallback callback, - gpointer user_data -); - -/** - * @brief Définit le callback de demande d'ajout d'une relation. - * - * Le Workspace relaie uniquement l'événement du volet de détails. - * - * @param workspace Zone de travail. - * @param callback Callback facultatif. - * @param user_data Données empruntées transmises au callback. - */ -void workspace_set_add_relation_callback( - Workspace *workspace, - WorkspaceAddRelationCallback callback, - gpointer user_data -); - -/** @brief Définit le callback de modification d'une relation. */ -void workspace_set_edit_relation_callback( - Workspace *workspace, - WorkspaceEditRelationCallback callback, - gpointer user_data -); -/** @brief Définit le callback de suppression d'une relation. */ -void workspace_set_delete_relation_callback(Workspace *workspace, - WorkspaceDeleteRelationCallback callback, gpointer user_data); - -/** - * @brief Définit le callback de sélection d'une relation. - * - * @param workspace Zone de travail. - * @param callback Callback facultatif. - * @param user_data Données empruntées transmises au callback. - */ -void workspace_set_relation_selected_callback( - Workspace *workspace, - WorkspaceRelationSelectedCallback callback, - gpointer user_data -); - -/** - * @brief Affiche les preuves associées à la relation sélectionnée. - * - * @param workspace Zone de travail. - * @param evidence_records Tableau emprunté de EvidenceRecord, ou NULL. - */ -void workspace_set_relation_evidences( - Workspace *workspace, - const GPtrArray *evidence_records -); - -/** @brief Définit le callback de catégorisation d'une personne. */ -void workspace_set_person_role_callback(Workspace *workspace, - WorkspacePersonRoleCallback callback, gpointer user_data); -/** @brief Définit le callback de confiance d'une personne. */ -void workspace_set_person_confidence_callback(Workspace *workspace, - WorkspacePersonConfidenceCallback callback, gpointer user_data); - -/** - * @brief Affiche l'état de chargement du graphe. - * - * L'ancien graphe emprunté est détaché. - * - * @param workspace Zone de travail. - */ -void workspace_set_graph_loading( - Workspace *workspace -); -/** @brief Définit le callback de modification du nom affiché. */ -void workspace_set_person_name_callback(Workspace *workspace, - WorkspacePersonNameCallback callback, gpointer user_data); -/** @brief Définit le callback de gestion des preuves d'une personne. */ -void workspace_set_person_evidence_callback(Workspace *workspace, - WorkspacePersonEvidenceCallback callback, gpointer user_data); -void workspace_set_evidence_activated_callback( - Workspace *workspace, - WorkspaceEvidenceActivatedCallback callback, - gpointer user_data); -/** @brief Définit le callback de sélection d'une entité. */ -void workspace_set_entity_selected_callback(Workspace *workspace, - WorkspaceEntitySelectedCallback callback, gpointer user_data); -/** @brief Affiche les preuves de la personne sélectionnée. */ -void workspace_set_person_evidences(Workspace *workspace, - const GPtrArray *records); -void workspace_set_person_factual_relations(Workspace *workspace, - const GPtrArray *relations, const GPtrArray *evidence_records,const GHashTable *profile_fields); - -/** - * @brief Affiche le graphe chargé avec sa disposition persistée. - * - * Le Workspace emprunte graph_model et graph_layout et ne les libère jamais. - * - * Passer NULL pour graph_model équivaut à workspace_clear_graph(). - * Passer NULL pour graph_layout conserve le placement automatique. - * - * @param workspace Zone de travail. - * @param graph_model Graphe emprunté. - * @param graph_layout Disposition empruntée, ou NULL. - */ -void workspace_set_graph( - Workspace *workspace, - const InvestigationGraphModel *graph_model, - const InvestigationGraphLayout *graph_layout -); - -gboolean workspace_get_graph_view_transform( - Workspace *workspace, double *zoom, double *offset_x, double *offset_y); -void workspace_set_graph_view_transform( - Workspace *workspace, double zoom, double offset_x, double offset_y); - -/** - * @brief Affiche une erreur de chargement du graphe. - * - * Le texte du message est immédiatement copié par GTK. - * - * @param workspace Zone de travail. - * @param message Détail de l'erreur, ou NULL. - */ -void workspace_set_graph_error( - Workspace *workspace, - const char *message -); - -/** - * @brief Détache le graphe et restaure l'état sans enquête. - * - * Le graphe précédemment emprunté n'est jamais libéré par le Workspace. - * - * @param workspace Zone de travail. - */ -void workspace_clear_graph( - Workspace *workspace -); - -/** - * @brief Reconstruit visuellement la disposition automatique du graphe. - * - * Cette fonction ne touche ni SQLite ni InvestigationGraphLayout. Elle doit - * être appelée par la couche applicative uniquement après la suppression - * réussie des positions persistées. - * - * Le zoom et le déplacement global du canvas sont conservés. - * - * @param workspace Zone de travail. - */ -void workspace_reset_graph_layout( - Workspace *workspace -); - -/** - * @brief Libère la structure Workspace. - * - * Cette fonction accepte NULL. Elle ne libère jamais le graphe emprunté. - * - * @param workspace Zone de travail à libérer. - */ -void workspace_free( - Workspace *workspace -); - -#endif diff --git a/prototypes/web-graph/public/app.js b/prototypes/web-graph/public/app.js index 0727a68..dadcab1 100644 --- a/prototypes/web-graph/public/app.js +++ b/prototypes/web-graph/public/app.js @@ -111,6 +111,7 @@ let navigationHistory = []; let collapsedGroups = new Set(); let filters = {}; let scale = 1; +let graph_scale_initialized = false; let offset = { x: 0, y: 0 }; let keyboardIndex = -1; let eventSource = null; @@ -126,6 +127,7 @@ let correlationsRefreshing = false; let correlationRevision = null; let plannerRevision = null; let plannerValue = null; +let researchValue = null; let specializedView = "graph"; const pinnedPositions = new Map(); const reportSelection = new Set(); @@ -156,6 +158,7 @@ function invalidateWorkspaceContext() { jobsRefreshing = false; graphRefreshing = false; correlationsRefreshing = false; + researchValue = null; } function beginWorkspaceContext(workspaceId, generation) { @@ -734,6 +737,148 @@ async function refreshPlanner() { } } +function researchDecision(actionId) { + return document.querySelector( + `input[name="research-${CSS.escape(actionId)}"]:checked`, + )?.value ?? "defer"; +} + +function renderResearch() { + // INVARIANT: toutes les cartes proviennent du snapshot C ; aucune action ou + // adresse de fournisseur n'est construite ni conservée comme vérité JS. + const panel = byId("research-plan"); + panel.replaceChildren(); + if (!researchValue || researchValue.state === "EMPTY") { + byId("research-launch").disabled = true; + byId("research-revoke").disabled = true; + return; + } + const heading = document.createElement("h4"); + heading.textContent = `Question : ${researchValue.question}`; + panel.append(heading); + const waveOneDone = researchValue.actions.some( + (action) => action.wave === 1 && action.contacted, + ); + for (const action of researchValue.actions) { + const card = document.createElement("article"); + card.className = "research-card"; + const title = document.createElement("h5"); + title.textContent = `Vague ${action.wave} · ${action.capability_id}`; + const explanation = document.createElement("p"); + explanation.textContent = action.wave === 1 + ? "Gain attendu : obtenir un fait sourcé. Incertitude : le fournisseur peut ne rien connaître." + : action.wave === 2 + ? "Nouvelle action non contactée : vérifier ou contredire le premier résultat." + : "Action optionnelle distincte ; aucun contact sans autorisation explicite."; + const provenance = document.createElement("p"); + provenance.textContent = `Source/provenance : sélection du graphe · sujet exact : ${action.subject}`; + const disclosure = document.createElement("p"); + disclosure.textContent = `Fournisseur : ${action.provider_id} · contact ${action.contact} · ${action.disclosure}`; + const budget = document.createElement("p"); + budget.textContent = `Budget maximal : ${action.max_requests} requête · ${action.max_response_bytes} octets · ${action.max_active_ms} ms.`; + const status = document.createElement("p"); + status.className = action.contacted ? "research-contacted" : "research-uncontacted"; + status.textContent = action.contacted + ? `Résultat : ${action.result_status || "MISSING"}` + : "Non contactée — aucune donnée fournisseur reçue."; + const choices = document.createElement("fieldset"); + choices.disabled = action.contacted || (action.wave === 2 && !waveOneDone); + const legend = document.createElement("legend"); + legend.textContent = "Décision humaine"; + choices.append(legend); + for (const [value, label] of [["authorize", "Autoriser"], + ["defer", "Différer"], ["refuse", "Refuser"]]) { + const choice = document.createElement("label"); + const input = document.createElement("input"); + input.type = "radio"; + input.name = `research-${action.action_id}`; + input.value = value; + input.checked = value === (action.decision?.toLowerCase() ?? "defer"); + input.addEventListener("change", () => { + byId("research-launch").disabled = !researchValue.actions.some( + (item) => !item.contacted && researchDecision(item.action_id) === "authorize", + ); + }); + choice.append(input, ` ${label}`); + choices.append(choice); + } + card.append(title, explanation, provenance, disclosure, budget, status, choices); + panel.append(card); + } + byId("research-launch").disabled = true; + byId("research-revoke").disabled = !researchValue.grants.some( + (grant) => !grant.revoked_at, + ); +} + +async function refreshResearch() { + if (!operationalMode) return; + const response = await workspaceFetch("/api/v1/research", { cache: "no-store" }); + const value = await workspaceJson(response); + if (!response.ok || value.contract !== "labfy.research.snapshot.v1") + throw new Error(value.message ?? "Recherche indisponible"); + researchValue = value; + renderResearch(); +} + +async function prepareResearch() { + const node = selectedNode(); + if (!node) throw new Error("Sélectionnez d’abord une preuve ou une entité."); + const exclusions = byId("research-exclusions").value.split("\n") + .map((item) => item.trim()).filter(Boolean); + researchValue = await postCommand("/api/v1/research/prepare", { + selection_ids: [node.id], + question: byId("research-question").value.trim(), + exclusions, + idempotency_key: crypto.randomUUID(), + }); + byId("research-note").textContent = + "Plan préparé par le cœur C. Choisissez chaque action avant le lancement final."; + renderResearch(); +} + +async function launchResearch() { + const actionIds = researchValue.actions.filter((action) => + !action.contacted && researchDecision(action.action_id) === "authorize") + .map((action) => action.action_id); + if (!actionIds.length) return; + const exclusions = byId("research-exclusions").value.split("\n") + .map((item) => item.trim()).filter(Boolean); + const decisions = researchValue.actions.map((action) => ({ + action_id: action.action_id, + decision: researchDecision(action.action_id).toUpperCase(), + })); + const grant = await postCommand("/api/v1/research/grants", { + plan_id: researchValue.plan_id, + input_revision: researchValue.input_revision, + selected_action_ids: actionIds, + decisions, + exclusions, + idempotency_key: crypto.randomUUID(), + }); + const grantId = grant.grants[0]?.grant_id; + if (!grantId) throw new Error("Autorisation durable absente."); + researchValue = await postCommand("/api/v1/research/campaigns", { + grant_id: grantId, + input_revision: grant.input_revision, + action_ids: actionIds, + idempotency_key: crypto.randomUUID(), + }); + byId("research-note").textContent = + "Campagne terminée ; résultats sourcés et actions non contactées affichés."; + renderResearch(); +} + +async function revokeResearch() { + const grant = [...researchValue.grants].reverse().find((item) => !item.revoked_at); + if (!grant) return; + researchValue = await postCommand("/api/v1/research/revoke", { + grant_id: grant.grant_id, + }); + byId("research-note").textContent = "Autorisation révoquée durablement."; + renderResearch(); +} + const renderer = new GraphRenderer({ svg, viewport: byId("viewport"), @@ -1233,7 +1378,9 @@ function resetGlobalView() { focusNodeId = null; filters = {}; collapsedGroups.clear(); - scale = 1; + // CONTRACT: « Réinitialiser » revient à la vue globale visible. Une échelle + // fixe à 1 ferait sortir le snapshot cœur sous les panneaux persistants. + scale = snapshot.nodes.length > 0 ? fitGraphScale() : 1; offset = { x: 0, y: 0 }; keyboardIndex = -1; specializedView = "graph"; @@ -1338,6 +1485,24 @@ function updateProjectionControls() { } function configureControls() { + // CONTRACT: la disposition est une préférence locale par origine ; elle ne + // transporte ni l'enquête, ni un secret, ni un état métier vers le navigateur. + for (const button of document.querySelectorAll(".pane-toggle")) { + const pane = byId(button.dataset.pane); + const key = `labfy-pane:${button.dataset.pane}`; + const apply = (collapsed) => { + pane.classList.toggle("pane-collapsed", collapsed); + button.setAttribute("aria-expanded", String(!collapsed)); + button.textContent = collapsed ? "Déployer" : "Réduire"; + requestAnimationFrame(() => renderer.updateViewport(scale, offset)); + }; + apply(localStorage.getItem(key) === "collapsed"); + button.addEventListener("click", () => { + const collapsed = !pane.classList.contains("pane-collapsed"); + localStorage.setItem(key, collapsed ? "collapsed" : "expanded"); + apply(collapsed); + }); + } for (const tab of document.querySelectorAll("[data-panel]")) { tab.addEventListener("click", () => activateInspectorPanel(tab.dataset.panel), @@ -1359,6 +1524,7 @@ function configureControls() { .classList.toggle("drawer-collapsed", collapsed); event.currentTarget.setAttribute("aria-expanded", String(!collapsed)); event.currentTarget.textContent = collapsed ? "Déployer" : "Réduire"; + localStorage.setItem("labfy-pane:drawer", collapsed ? "collapsed" : "expanded"); requestAnimationFrame(() => renderer.updateViewport(scale, offset)); }); byId("view-evidence").addEventListener("click", () => { @@ -1458,6 +1624,23 @@ function openNodeContextMenu(nodeId, clientX, clientY) { } function configureGraphInteractions() { + // WHY: les panneaux persistants modifient réellement la largeur SVG. Le + // renderer doit recaler son viewport avant le prochain drag, sans muter les + // coordonnées épinglées qui restent un état de présentation local. + new ResizeObserver(() => requestAnimationFrame(() => { + const panel = byId("graph-panel"); + if (!graph_scale_initialized && snapshot.nodes.length > 0 && + panel.clientWidth > 100 && panel.clientHeight > 100) { + // WHY: le snapshot peut arriver pendant que la coque tri-panneaux passe + // de hidden à sa largeur finale. L'auto-fit unique évite que des nœuds + // SVG débordent sous Activité, tout en préservant ensuite zoom/pins. + scale = fitGraphScale(); + graph_scale_initialized = true; + render(); + return; + } + renderer.updateViewport(scale, offset); + })).observe(byId("graph-panel")); let pan = null; svg.addEventListener("pointerdown", (event) => { if (event.target !== svg && event.target.id !== "graph-background") return; @@ -1624,6 +1807,7 @@ function resetWorkspacePresentation() { plannerValue = null; preparedUploads.clear(); pinnedPositions.clear(); + graph_scale_initialized = false; resetGlobalView(); } @@ -1646,6 +1830,9 @@ async function activateWorkspace(opened) { snapshot = prepareSnapshot(value); acceptedSnapshotFingerprint = snapshotFingerprint(value); coreMode = snapshot.origin === "core"; + // CONTRACT: la mesure suit la publication de la coque visible ; elle ne + // repose pas sur la largeur héritée lorsque le shell était hidden. + await new Promise((resolve) => requestAnimationFrame(resolve)); scale = fitGraphScale(); syncTypeFilterOptions(); restoreReportDraft(); @@ -1653,7 +1840,8 @@ async function activateWorkspace(opened) { renderTimeline(); renderReportSelection(); byId("connection").textContent = `Ouverte · génération ${opened.generation}`; - await Promise.all([refreshJobs(), refreshCorrelations(), refreshPlanner()]); + await Promise.all([refreshJobs(), refreshCorrelations(), refreshPlanner(), + refreshResearch()]); for (const [callback, delay] of [[refreshJobs, 500], [refreshOperationalGraph, 700], [refreshCorrelations, 900], [refreshPlanner, 1100]]) refreshTimers.add(setInterval(callback, delay)); @@ -1684,6 +1872,9 @@ async function activateLegacyWorkspace(session) { snapshot = prepareSnapshot(value); acceptedSnapshotFingerprint = snapshotFingerprint(value); coreMode = snapshot.origin === "core"; + // CONTRACT: le snapshot cœur doit être ajusté après le layout Agent | + // Graphe | Activité, sinon ses coordonnées SVG débordent sous Activité. + await new Promise((resolve) => requestAnimationFrame(resolve)); byId("mode-badge").textContent = operationalMode ? "Poste local · contrôles locaux" : coreMode ? "Snapshot du cœur C · lecture seule" : "Démonstration locale · lecture seule"; @@ -1700,7 +1891,8 @@ async function activateLegacyWorkspace(session) { byId("graph-state").textContent = `Snapshot cœur indisponible : ${snapshot._loadError}`; if (!coreMode) connectEvents(); if (operationalMode) { - await Promise.all([refreshJobs(), refreshCorrelations(), refreshPlanner()]); + await Promise.all([refreshJobs(), refreshCorrelations(), refreshPlanner(), + refreshResearch()]); for (const [callback, delay] of [[refreshJobs, 500], [refreshOperationalGraph, 700], [refreshCorrelations, 900], [refreshPlanner, 1100]]) refreshTimers.add(setInterval(callback, delay)); @@ -1751,6 +1943,20 @@ function configureApplication() { configureControls(); configureGraphInteractions(); configureImport(); + const drawerCollapsed = localStorage.getItem("labfy-pane:drawer") === "collapsed"; + if (drawerCollapsed && !byId("work-panel").classList.contains("collapsed")) + byId("work-panel-toggle").click(); + byId("agent-send").addEventListener("click", () => { + const prompt = byId("agent-prompt").value.trim(); + if (!prompt) { byId("agent-prompt").focus(); return; } + const card = document.createElement("li"); + card.className = "agent-card user"; + const label = document.createElement("b"); label.textContent = "USER"; + const text = document.createElement("p"); text.textContent = prompt; + card.append(label, text); + document.querySelector(".agent-conversation").append(card); + byId("agent-prompt").value = ""; + }); byId("home-button").addEventListener("click", () => void showLibrary({ focus: true })); byId("workspace-create-form").addEventListener("submit", async (event) => { event.preventDefault(); @@ -1788,6 +1994,27 @@ function configureApplication() { } finally { button.disabled = false; } }); byId("jobs-note").textContent = "Contrôle local authentifié."; + byId("research-form").addEventListener("submit", (event) => { + event.preventDefault(); + byId("research-note").textContent = "Préparation…"; + void prepareResearch().catch((error) => { + if (error.name !== "AbortError") + byId("research-note").textContent = error.message; + }); + }); + byId("research-launch").addEventListener("click", () => { + byId("research-note").textContent = "Admission et campagne…"; + void launchResearch().catch((error) => { + if (error.name !== "AbortError") + byId("research-note").textContent = error.message; + }); + }); + byId("research-revoke").addEventListener("click", () => + void revokeResearch().catch((error) => { + if (error.name !== "AbortError") + byId("research-note").textContent = error.message; + }), + ); for (const [id, command] of [ ["queue-pause", "pause"], ["queue-resume", "resume"], diff --git a/prototypes/web-graph/public/index.html b/prototypes/web-graph/public/index.html index 905fda7..5e84b6d 100644 --- a/prototypes/web-graph/public/index.html +++ b/prototypes/web-graph/public/index.html @@ -91,6 +91,20 @@
+
@@ -147,10 +161,17 @@
+