Compare commits

...

2 Commits

Author SHA1 Message Date
29a85bdcf7
docs(evolution): intégration revue critique + réorganisation complète
Revue critique (claude.ai) intégrée :
- Point 3 : versionnage formules indices + date disponibilité effective
- Point 4 : critères sélection amorçage (stresser les mécanismes)
- Point 6 : réversibilité dans le spike technique
- Point 7 : SCOR/ISO en contrepoint, axes validation complémentaires
- Point 8 : interface concrète IRON (3 cas d'usage)
- Point 12 : projection qualitative/chiffrée selon confiance, rétro-analyse calibration
- Point 13 : deux sorties bus (situationnelle/structurelle), coût IA différé
- Contraintes transversales : décisions différées avec signaux déclencheurs

Réorganisation document :
- Vue 1 en en-tête (principe fondamental)
- Ordre de réalisation aligné sur les 4 vues
- Progression architecturale (Vue 1→4) en fin de document
- DAF et DAT mis à jour (8 fonctions, bus d'impact, structurel/situationnel)
- Vue 4 corrigée (veille propose, ne injecte pas ; flèche API restaurée ;
  sortie structurelle du bus)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:08:27 +02:00
e6ff714fca
docs(evolution): réorganisation docs/FabNum v2/ + points 13-14 + vues progressives
- Déplacement de toute la documentation v2 dans docs/FabNum v2/
- Ajout points 13 (bus d'impact, mémoire situationnelle, IA) et 14 (combinatoire)
- Architecture structurel/situationnel, IVC dynamique inter-sectoriel
- 4 vues architecturales progressives (vue1→vue4) pour présentation
- Génération PNG de tous les diagrammes
- .gitignore : docs/**/*.dot au lieu de docs/*.dot

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 11:54:52 +02:00
27 changed files with 1124 additions and 339 deletions

2
.gitignore vendored
View File

@ -7,7 +7,7 @@ __pycache__/
*.pyo
*.pyd
*.dot
!docs/*.dot
!docs/**/*.dot
prompt.md
.gitignore

View File

@ -0,0 +1,119 @@
# Instructions de révision — EVOLUTIONS.md (FabNum)
Document issu d'une revue critique du brainstorming FabNum. Les instructions sont organisées par point du document source. Elles portent sur le fond uniquement ; la forme sera traitée séparément.
## Contraintes transversales
Ajouter une mention explicite que deux questions sont des **décisions différées**, conditionnées au modèle de financement du projet :
- La portée de l'open source (moteur, graphe des essentiels, services).
- La dé-concentration du bus factor.
Pour chacune, identifier le ou les **signaux déclencheurs** qui imposeront l'arbitrage : premier prospect sérieux, premier financement, premier contributeur externe, demande client de garantie de continuité, SLA contractuel. L'objectif n'est pas de trancher maintenant mais de garantir que la décision ne sera pas prise par défaut ou dans l'urgence.
## Point 3 — Modèle de données structuré
### Versionnage des indices
Ajouter comme exigence de l'historisation : chaque valeur d'indice stockée porte la référence à la version de formule qui l'a calculée. Le cas de l'ISG (dont un indice constitutif vient de changer de méthode) illustre directement le besoin.
Deux implications à capturer :
- La coexistence de plusieurs versions de formule dans l'historique doit être supportée nativement. On ne recalcule pas rétroactivement avec la nouvelle formule, sinon on perd la trace de ce qu'on voyait à l'époque.
- Le versionnage de formule interagit avec le versionnage des données. Une valeur d'indice historisée est fonction de (formule_v, données_à_date). Pour rejouer proprement, il faut pouvoir reconstituer les deux.
### Horodatage « date de disponibilité effective »
Étendre l'historisation pour que chaque donnée porte non seulement la valeur et sa date de validité métier, mais aussi la date à laquelle elle est devenue connue (date de disponibilité effective). Sans cela, la rétro-analyse souffre d'un look-ahead bias : on rejouerait une crise passée avec des données que personne ne connaissait à l'époque.
Cette exigence s'applique à toutes les données qui entrent dans les indices, pas seulement aux stocks.
## Point 4 — Amorçage
Reformuler le choix du périmètre autour du principe : le périmètre est choisi **pour** stresser les mécanismes qualité, pas malgré eux. Si les minerais retenus passent tous les filtres sans déclencher d'arbitrage, les filtres n'ont pas été testés.
Critères de sélection à acter :
- Au moins un minerai aux sources opaques ou divergentes (candidats : germanium, gallium, terres rares côté chinois).
- Au moins un minerai avec débat méthodologique extraction/raffinage (candidats : lithium, cobalt — terrain déjà travaillé sur gallium et hafnium).
- Un minerai bien documenté comme témoin (candidats : cuivre, fer).
- Pour le composant : pas le plus simple, mais un dont la chaîne a des zones d'ombre.
## Point 6 — Stockage
Ajouter au spike technique un critère d'évaluation : **réversibilité par rapport aux décisions différées** (open source, modèle commercial). L'objectif n'est pas de trancher à la place du modèle de financement, mais d'éviter de fermer prématurément des portes qu'on ne voulait pas fermer.
Exemple de tension à capturer : Neo4j Community est indolore à faire évoluer vers Enterprise, mais un passage à PostgreSQL+AGE ou ArangoDB ne l'est pas. Inversement, PostgreSQL+AGE laisse plus d'options ouvertes côté licence au prix d'une maturité graphe moindre.
## Point 7 — Validation du modèle de niveaux
Séparer clairement les deux méthodes de validation, qui portent sur deux axes différents et sont **complémentaires, pas alternatives** :
- **Axe vertical (quels niveaux, quels intitulés génériques)** — validé par revue de littérature. Références pertinentes pour la décomposition matière : USGS mineral commodity summaries et flux de matières, études JRC sur les matières premières critiques, travaux de l'IEA sur les chaînes de valeur énergie-matière, analyses de cycle de vie matière (ACV).
- **Axe horizontal (jusqu'où remonter dans la profondeur des dépendances)** — validé par démonstration via les marges d'erreur cumulées. Pas de bibliographie nécessaire sur cet axe, c'est un argument analytique.
Préciser que SCOR et ISO 28000 peuvent être mentionnés mais en contrepoint uniquement : ils traitent de la gestion process de la supply chain, pas de la décomposition matière. Les utiliser comme benchmark principal ferait porter la validation sur le mauvais objet.
## Point 8 — Services, sécurisation et profils de visibilité
Ajouter un paragraphe (pas un point à part entière) sur l'interface concrète avec IRON. Le couplage est actuellement mentionné en une ligne dans les contraintes transversales mais on ne sait pas comment il se matérialise. FabNum ne se substitue pas à IRON, il le complète : FabNum fournit le diagnostic de fragilité technique de la chaîne, IRON évalue la capacité organisationnelle à encaisser et contourner (distinction Hamant résilience/robustesse).
Décrire deux ou trois usages concrets d'appel croisé. Pistes à explorer :
- IRON consomme des analyses FabNum via l'API comme intrants de l'évaluation Y-axis ou Z-axis.
- FabNum produit en sortie une liste de dépendances critiques qu'IRON utilise dans son diagnostic.
- Un score IRON peut en retour contextualiser une analyse FabNum : pour cette organisation donnée, telle dépendance est critique parce que leur robustesse sur ce point est faible.
Sans cette explicitation, le couplage reste déclaratif et risque de ne jamais être implémenté.
## Point 12 — Stocks et projection temporelle
### Résultat qualitatif par défaut
Reformuler pour dire explicitement que la projection temporelle produit un résultat **qualitatif** (court / moyen / long terme, ou équivalent à calibrer) et non une valeur en mois. Remplacer l'exemple actuel (« ~8 mois avant impact ») par une formulation du type « impact court terme (semaines), moyen terme (quelques mois), long terme (au-delà) » avec l'indice de confiance associé.
Cohérent avec le principe directeur du point 3 : « on travaille avec des estimations, pas des mesures exactes ».
### Indice de confiance hérité
L'indice de confiance de la projection hérite par propagation de l'indice de fiabilité des données de stock mobilisées. Ce n'est pas un nouvel indice à concevoir.
### Rétro-analyse comme mécanisme de calibration
La rétro-analyse mentionnée dans le MVP (Spruce Pine, quotas chinois) prend un double rôle : preuve de concept des indices **et** mécanisme de calibration du moteur de projection. On rejoue une crise passée dont on connaît le déroulement réel, on observe ce que le moteur aurait prédit avec les données de l'époque, on ajuste les seuils court/moyen/long terme.
À articuler avec la rétro-analyse des indices : pour une crise passée donnée, rejouer avec **les deux** versions de formule quand c'est pertinent — formule de l'époque (qu'aurions-nous vu venir avec les outils d'alors ?) et formule actuelle (le moteur actuel capte-t-il bien le signal ?). Si la nouvelle formule ne capte pas mieux une crise passée que l'ancienne, la révision n'a rien apporté.
## Point 13 — Bus d'impact
### Deux sorties possibles, tri par l'expert
Rendre explicite que le bus d'impact a **deux sorties possibles** et que le tri entre elles fait partie de la décision de l'expert :
- Sortie situationnelle — impact temporaire sur les capacités réelles (inondation, blocage logistique, grève).
- Sortie structurelle — modification de la capacité nominale elle-même (fermeture définitive de mine, ouverture d'un nouvel opérateur, quota devenu politique permanente, reconfiguration durable d'une route).
L'IA du bus propose, l'expert arbitre entre les deux couches. Sans cette précision, un développeur (ou Claude Code au moment de l'implémentation) risque de coder le bus comme un pipeline mono-sortie vers le situationnel, et une fermeture de mine atterrirait comme un impact « -100% permanent » au lieu d'une modification du graphe structurel.
### Coût opérationnel de l'IA
Mentionner que le coût opérationnel de l'IA est un élément à chiffrer **au moment où la Vue 4 devient l'étape courante**, pas avant et pas après. Cela évite deux écueils symétriques : chiffrer trop tôt (purement spéculatif) ou découvrir tardivement que le modèle économique du bus ne boucle pas.
Ajouter que l'expérience du générateur de rapport actuel (modèles gratuits) fournit une base empirique pour extrapoler l'ordre de grandeur le moment venu. Cela ancre l'estimation future dans du concret plutôt que dans un calcul théorique.
## Vue 4 — Schéma à corriger
Trois corrections sur la figure :
1. **Flèche Écosystème veille 360° → Bus d'impact** : actuellement étiquetée « injecte des événements », ce qui contredit le texte du point 13. La veille propose, elle n'injecte pas. Redessiner comme une flèche « propose des événements » vers l'Expert (ou vers une file d'attente validée par l'expert), symétrique à la flèche « propose des sources » qui existe déjà.
2. **Flèche Écosystème veille 360° → API** : perdue par rapport à la Vue 3. Ce canal ne disparaît pas en Vue 4, il s'ajoute au canal de proposition. L'écosystème 360° a deux usages en régime complet : consommateur d'analyses via API, pourvoyeur d'événements et de sources via validation expert. Les deux doivent apparaître.
3. **Flèche Expert → Graphe structurel** (via Moteur) : absente. La flèche « valide les impacts » Expert → Bus d'impact est présente et correcte, mais il manque le chemin par lequel les modifications structurelles validées hors cycle trimestriel (fermeture de mine, nouvel opérateur) atteignent le graphe structurel. Sans ce chemin, la sortie structurelle du bus n'a pas de destination visible.
## Points hors périmètre de la révision
Deux remarques initiales ont été écartées après discussion et ne sont pas à traiter dans la révision du document :
- **Bus factor et régime de validation du bus d'impact** : le document est précisément écrit pour lever le bus factor. Maintenir le régime « validation expert obligatoire » tel quel.
- **FabNum comme « nième outil de criticité »** : formulation incorrecte. Le paysage public des outils de criticité supply chain appliqués au numérique est très peu couvert ; les rares outils opérationnels pointus sont gouvernementaux ou propriétaires non publiés. FabNum occupe un espace réel.

View File

@ -5,6 +5,12 @@ Document de brainstorming — capture les réflexions et décisions prises lors
**Date** : 2026-04-02
**Statut** : En cours de réflexion (quoi/pourquoi, pas encore le comment)
## Principe fondamental
FabNum v2 est un **moteur d'analyse** des risques géopolitiques sur les chaînes d'approvisionnement, exposé via une **API**. L'interface actuelle Streamlit est abandonnée au profit d'un frontend consommant l'API. L'administration se fait par scripts.
![Vue 1 — Le moteur](architecture-vue1.png){ width=100% }
## Contraintes transversales
- **Budget : zéro en phase de démarrage** — tout est auto-hébergé et auto-financé. Briques technologiques open source et gratuites. Si le projet trouve son marché, cette contrainte sera réévaluée (ex : Neo4j Enterprise si justifié).
@ -15,9 +21,13 @@ Document de brainstorming — capture les réflexions et décisions prises lors
- **Intégration écosystème** — FabNum est un composant d'un écosystème plus large de veille stratégique 360° sur la polycrise. Il sera requêté par d'autres outils pour fournir des analyses et rapports.
- **Couplage** — FabNum se couple avec la méthodologie [IRON](https://conseil.peccini.fr/iron/) et le livre blanc "Voyage vers la robustesse".
- **Personas cibles** — COMEX (vision stratégique, synthèses), Métiers (analyse opérationnelle), DSI (dépendances SI).
- **Open source** — la question de ce qui sera open source (moteur, graphe des essentiels) reste à trancher.
- **Choix technologiques structurants** — base de données, framework API, frontend expert : à définir rapidement en début d'implémentation.
**Décisions différées** — conditionnées au modèle de financement, à ne pas trancher maintenant mais à ne pas laisser arriver par défaut ou dans l'urgence :
- **Portée de l'open source** (moteur, graphe des essentiels, services). Signaux déclencheurs : premier prospect sérieux, premier financement, demande client de garantie de continuité.
- **Dé-concentration du bus factor**. Signaux déclencheurs : premier contributeur externe, SLA contractuel, premier financement permettant de diversifier.
---
## Point 1 — Recentrage de FabNum : moteur + API + séparation des rôles
@ -110,6 +120,11 @@ Un **indice de fiabilité de la donnée** agrège plusieurs facteurs : granulari
**Historisation** — chaque donnée, chaque valeur d'indice, chaque état du graphe est horodaté et conservé. Nécessaire pour la détection de tendances, les alertes de variation, et la rétro-analyse (backtesting des indices sur des crises passées : Spruce Pine, quotas chinois, etc.).
Exigences complémentaires de l'historisation :
- **Versionnage des formules d'indices** — chaque valeur d'indice stockée porte la référence à la version de formule qui l'a calculée (ex : l'ISG a changé de méthode de calcul suite à l'évolution d'un indice constitutif). On ne recalcule pas rétroactivement avec la nouvelle formule : on conserve ce qu'on voyait à l'époque. La coexistence de plusieurs versions de formule dans l'historique est supportée nativement. Une valeur historisée est fonction de (formule_version, données_à_date).
- **Date de disponibilité effective** — chaque donnée porte non seulement sa valeur et sa date de validité métier, mais aussi la date à laquelle elle est devenue connue. Sans cela, la rétro-analyse souffre d'un look-ahead bias : on rejouerait une crise passée avec des données que personne ne connaissait à l'époque. S'applique à toutes les données entrant dans les indices.
Les spécifications servent aussi de **cahier des charges pour la recherche de sources** : si une donnée essentielle n'a pas de source, on sait précisément ce qu'on cherche.
### Pourquoi
@ -153,7 +168,11 @@ Alimenter la base de données structurée (point 3) à partir des fiches actuell
### Décisions prises
- **Qualification progressive** — chaque donnée et chaque source est passée au crible des filtres qualité (tier de confiance, vérification citation, périmètre). Ce qui passe est conservé comme donnée de référence, ce qui ne passe pas est remplacé ou supprimé. Ce n'est pas "test puis jeter", c'est un processus de qualification.
- Le périmètre d'amorçage (tout le corpus ou un sous-ensemble) reste à décider.
- **Périmètre choisi pour stresser les mécanismes qualité** — si les minerais retenus passent tous les filtres sans déclencher d'arbitrage, les filtres n'ont pas été testés. Critères de sélection :
- Au moins un minerai aux sources opaques ou divergentes (candidats : germanium, gallium, terres rares côté chinois)
- Au moins un minerai avec débat méthodologique extraction/transformation (candidats : lithium, cobalt)
- Un minerai bien documenté comme témoin (candidats : cuivre, fer)
- Un composant dont la chaîne a des zones d'ombre (pas le plus simple)
- Les fiches existantes ne sont pas modifiées à cette étape.
- Cet amorçage sert aussi de validation des chantiers précédents.
@ -220,7 +239,7 @@ Cette architecture composable permet de gérer la complexité sans surcharger le
### Décisions prises
- Le DOT n'est plus le stockage primaire.
- Le choix technologique (base graphe type Neo4j Community, PostgreSQL+AGE, ArangoDB, ou autre) reste ouvert. Toutes les options sont open source.
- Le choix technologique (base graphe type Neo4j Community, PostgreSQL+AGE, ArangoDB, ou autre) reste ouvert. Toutes les options sont open source. Critère supplémentaire du spike : **réversibilité par rapport aux décisions différées** (open source, modèle commercial). Neo4j Community évolue facilement vers Enterprise, mais un passage à PostgreSQL+AGE ne l'est pas. Inversement, PostgreSQL+AGE laisse plus d'options ouvertes côté licence au prix d'une maturité graphe moindre.
- **Backup** : stratégie de sauvegarde à définir, mais simplifiée par la cadence d'évolution modérée du graphe.
- **Cadence de mise à jour** : mensuelle au démarrage (pour roder le workflow), puis trimestrielle une fois stabilisé. Alertes veille hors cadence pour les événements critiques.
- L'architecture multi-graphes (essentiel/connexe) est identifiée comme point futur à part entière.
@ -238,10 +257,10 @@ Revoir et valider les niveaux de décomposition de la chaîne de valeur. Deux ax
### Méthode de validation
La validation doit être **argumentée**, par au moins une des approches suivantes :
La validation porte sur **deux axes complémentaires** (pas alternatifs) :
- **Revue de littérature** — benchmark avec les modèles de chaînes d'approvisionnement existants, incluant les standards du domaine (SCOR model, ISO 28000, Open Supply Hub, Responsible Minerals Initiative).
- **Démonstration par les marges d'erreur** — montrer qu'avec les niveaux d'erreur cumulés le long de la chaîne, ajouter des niveaux n'améliorerait pas la précision des résultats.
- **Axe vertical (quels niveaux, quels intitulés génériques)** — validé par **revue de littérature**. Références pertinentes pour la décomposition matière : USGS mineral commodity summaries et flux de matières, études JRC sur les matières premières critiques, travaux IEA sur les chaînes de valeur énergie-matière, analyses de cycle de vie matière (ACV), Open Supply Hub, Responsible Minerals Initiative. Note : SCOR et ISO 28000 traitent de la gestion process de la supply chain, pas de la décomposition matière — à mentionner en contrepoint uniquement, pas comme benchmark principal.
- **Axe horizontal (jusqu'où remonter dans la profondeur des dépendances)** — validé par **démonstration via les marges d'erreur** cumulées. Montrer qu'ajouter des niveaux n'améliorerait pas la précision des résultats. Pas de bibliographie nécessaire, c'est un argument analytique.
### Pourquoi
@ -254,6 +273,10 @@ La validation doit être **argumentée**, par au moins une des approches suivant
- Quels intitulés génériques pour les niveaux ? (à définir après revue de littérature)
- Le nombre de niveaux doit-il être fixe ou configurable par chaîne ?
### Modèle de niveaux — Cas possibles
![Modèle de niveaux — Cas possibles](modele-niveaux-cas-possibles.png){ width=100% }
---
## Point 8 — Services, sécurisation et profils de visibilité
@ -311,6 +334,12 @@ Définir les services exposés par l'API, leur sécurisation et les niveaux de v
- Rôles (ce qu'on peut faire) et profils (ce qu'on peut voir) sont deux axes distincts.
- Moteur stateless côté données client (objectif), agent local client ou export manuel comme alternatives.
**Interface concrète avec IRON** — FabNum ne se substitue pas à IRON, il le complète. FabNum fournit le diagnostic de fragilité technique de la chaîne, IRON évalue la capacité organisationnelle à encaisser et contourner (distinction Hamant résilience/robustesse). Usages concrets d'appel croisé :
- IRON consomme des analyses FabNum via l'API comme intrants de l'évaluation Y-axis ou Z-axis.
- FabNum produit en sortie une liste de dépendances critiques qu'IRON utilise dans son diagnostic.
- Un score IRON peut en retour contextualiser une analyse FabNum : pour une organisation donnée, telle dépendance est critique parce que leur robustesse sur ce point est faible.
---
## Point 9 — Multi-sectoriel et architecture des graphes
@ -418,13 +447,14 @@ Le niveau 3 ne sera pas atteignable pour tous les opérateurs, mais peut l'être
Intégrer les **niveaux de stock** comme donnée du graphe pour permettre des **scénarios de projection temporelle** : en cas de rupture d'approvisionnement, estimer le délai d'impact le long de la chaîne de valeur.
- **Stock comme attribut de nœud** — chaque nœud pertinent (opération, composant) porte une estimation de stock (en mois de consommation, tonnes, unités).
- **Moteur de projection** — simulation de rupture à un point du graphe et propagation temporelle : "la Chine coupe le germanium → les fibres optiques sont impactées dans X mois, les serveurs dans Y mois".
- **Moteur de projection** — simulation de rupture à un point du graphe et propagation temporelle. Le résultat est **qualitatif ou chiffré selon l'indice de confiance** : si la confiance est suffisante, une fourchette chiffrée ("impact dans 4-8 mois") ; sinon, un résultat qualitatif ("impact court terme / moyen terme / long terme") avec l'indice de confiance associé. L'indice de confiance de la projection hérite par propagation de l'indice de fiabilité des données de stock mobilisées — ce n'est pas un nouvel indice à concevoir.
- **Scénarios what-if** — un service de calcul dynamique, pas juste une requête sur le graphe.
- **Rétro-analyse comme calibration** — rejouer des crises passées (Spruce Pine, quotas chinois) dont on connaît le déroulement réel, observer ce que le moteur aurait prédit avec les données de l'époque (en respectant la date de disponibilité effective), ajuster les seuils court/moyen/long terme. Pour une crise donnée, rejouer avec les deux versions de formule quand c'est pertinent : formule de l'époque (qu'aurions-nous vu venir ?) et formule actuelle (le moteur actuel capte-t-il mieux le signal ?).
### Pourquoi
- Passe FabNum de l'analyse **statique** (photo de la criticité à un instant T) à l'analyse **dynamique** (projection temporelle en cas de rupture).
- Valeur très forte pour les clients : "votre SI dépend du germanium via les fibres optiques, vous avez ~8 mois avant impact en cas de coupure chinoise".
- Valeur très forte pour les clients : "votre SI dépend du germanium via les fibres optiques, impact estimé à moyen terme (4-8 mois) avec un indice de confiance de 0.4".
- Les crises récentes (quotas chinois, Spruce Pine) montrent que le délai d'impact est une information critique pour la prise de décision.
### Difficultés identifiées
@ -441,45 +471,224 @@ Intégrer les **niveaux de stock** comme donnée du graphe pour permettre des **
---
## Point 13 — Bus d'impact (traducteur d'événements externes)
### Quoi
Un **bus d'impact** qui maintient en continu un état situationnel du graphe en traduisant les événements du monde extérieur en impacts chiffrés. Par analogie avec un bus applicatif, il possède une double connaissance :
- **Monde extérieur** — événements géopolitiques, climatiques, économiques, sanitaires, signaux faibles. Sources : veille 360°, actualités, données climatiques, alertes.
- **Monde intérieur** — le graphe FabNum, ses nœuds, ses attributs, ses limites (granularité géographique, disponibilité des données).
Le bus traduit un événement qualitatif ("inondation dans le Yunnan") en impacts quantitatifs sur des nœuds du graphe ("extraction de germanium dans le Yunnan : capacité réduite de 80%").
**Architecture structurel / situationnel :**
Le graphe FabNum a deux couches :
- **Graphe structurel** — la chaîne de valeur telle qu'elle existe : acteurs, pays, capacités nominales, parts de marché, indices. Mis à jour trimestriellement (cycle structurel).
- **Graphe situationnel** — le graphe structurel + les impacts en cours. Reflète la **réalité du terrain** à un instant T. Mis à jour en continu au rythme des événements (cycle situationnel).
Les deux cycles sont **indépendants** :
- Le cycle structurel (trimestriel) met à jour les données de base : qui opère quoi, où, avec quelle capacité nominale.
- Le cycle situationnel (continu, au **rythme décisionnel** — dans l'heure pour un événement majeur si un COMEX doit se réunir) met à jour la réalité : cette mine est inondée, Ormuz est bloqué, les quotas sont en vigueur.
**Le bus maintient une mémoire situationnelle** — il ne fait pas de traduction en one-shot. Les impacts s'accumulent, évoluent et se résolvent au fil du temps :
- Un événement arrive → impact ajouté
- La situation évolue ("l'inondation se résorbe") → impact mis à jour
- L'événement est résolu → impact supprimé ou archivé
Le graphe situationnel reflète ainsi en permanence la **situation mondiale réelle** et non un scénario ponctuel.
**Fonctionnement :**
- La **veille 360°** se connecte au bus et lui **propose** des événements (elle n'injecte pas directement).
- L'**IA** analyse l'événement, identifie les nœuds concernés et propose des impacts chiffrés (nœud impacté, type d'impact, pourcentage de réduction, durée estimée).
- Un **expert** valide ou corrige avant injection. Pas d'injection automatique non contrôlée.
- Le **moteur** se connecte au bus et consomme le graphe situationnel. Il n'a pas besoin de comprendre les événements — il travaille sur un graphe avec des capacités réelles.
**Deux sorties possibles du bus**, triées par l'expert :
- **Sortie situationnelle** — impact temporaire sur les capacités réelles (inondation, blocage logistique, grève). Alimente le graphe situationnel.
- **Sortie structurelle** — modification de la capacité nominale elle-même (fermeture définitive de mine, ouverture d'un nouvel opérateur, quota devenu politique permanente, reconfiguration durable d'une route). Alimente le graphe structurel hors cycle trimestriel.
L'IA propose la catégorie, l'expert tranche. Sans cette distinction, un développeur coderait le bus comme un pipeline mono-sortie vers le situationnel, et une fermeture de mine serait un impact "-100% permanent" au lieu d'une modification structurelle.
**Rôle de l'IA :**
La traduction événement → impact est un problème de **raisonnement** (comprendre l'événement, identifier les nœuds concernés, estimer la sévérité), pas d'algorithme. Un LLM avec accès au graphe et aux données contextuelles est le bon outil. Le code seul ne peut pas gérer l'infinie variété des événements possibles.
L'IA supervise aussi l'**évolution** de la situation : elle propose des mises à jour ("l'inondation au Yunnan est terminée, les mines reprennent à 60%"), l'expert valide.
**Signaux faibles :**
Le bus peut aussi traiter des signaux faibles (tensions diplomatiques, sécheresse naissante, changement de politique commerciale) avec une probabilité et une sévérité potentielle, permettant de construire des scénarios prospectifs.
**Indices structurels vs situationnels :**
Les indices se calculent sur les deux couches :
- **IHH structurel** (capacité nominale) vs **IHH situationnel** (capacité réelle avec impacts) — permet de mesurer la dégradation en cours.
- **IVC situationnel** — la pression concurrentielle des autres secteurs dépend de la situation mondiale. Si une crise ralentit l'automobile, sa consommation de cobalt chute et l'IVC effectif pour le numérique diminue. Au démarrage, calcul proportionnel ; à terme, ajustement dynamique basé sur les données de demande sectorielle. Ce point renforce le lien avec le multi-sectoriel (point 9) : l'IVC est le lien entre les secteurs sur les ressources partagées.
### Pourquoi
- Aujourd'hui, tester un scénario dans FabNum oblige à pointer manuellement un minerai et en déduire les impacts. Pas de lien avec le monde réel.
- Les crises sont rarement mono-causales — elles combinent plusieurs événements simultanés (Ormuz + sécheresse + quotas).
- La veille 360° a besoin d'un point d'entrée structuré pour alimenter le moteur.
- Sans ce bus, le moteur est aveugle aux événements extérieurs.
- Un graphe situationnel maintenu en continu donne aux clients une raison de rester connectés plutôt que de faire des analyses ponctuelles.
### Décisions prises
- Le bus d'impact est le **seul point de contact** entre le monde extérieur et le moteur — séparation des responsabilités.
- Le bus maintient une **mémoire situationnelle** — les impacts s'accumulent et évoluent, pas de one-shot.
- Deux couches de graphe : **structurel** (trimestriel) et **situationnel** (continu, rythme décisionnel).
- Les indices se calculent sur les deux couches (structurel vs situationnel).
- L'IA est un composant clé du bus (traduction et suivi), avec validation humaine obligatoire.
- Le bus a **deux sorties** (situationnelle et structurelle) — l'expert tranche.
- L'IVC situationnel dépend de la demande inter-sectorielle — proportionnel au démarrage, dynamique à terme.
- **Coût opérationnel de l'IA** — à chiffrer au moment où la Vue 4 devient l'étape courante, pas avant. L'expérience du générateur de rapport actuel (modèles gratuits) fournit une base empirique pour extrapoler l'ordre de grandeur.
- Point identifié comme horizon — dépend de la granularité géographique (point 11) et des stocks (point 12).
---
## Point 14 — Combinatoire multi-impacts et scénarios
### Quoi
Le moteur reçoit N impacts simultanés du bus (point 13), les applique sur le graphe et en déduit les conséquences cumulées via la projection temporelle (point 12).
Ce n'est **pas un composant actif** mais une **propriété du moteur** : s'il est conçu dès le départ pour recevoir des impacts multiples du bus, la combinatoire est native. C'est une contrainte de conception, pas un développement séparé.
**Concrètement :**
- Chaque impact du bus coupe ou réduit une ou plusieurs branches du graphe.
- Le moteur fait tourner la projection temporelle (point 12) sur le graphe dégradé.
- Le résultat montre quels produits finaux sont impactés, dans quel délai, avec quelle sévérité.
- Si deux événements coupent deux sources différentes d'un même minerai, l'impact combiné est pire que chaque événement seul — le moteur le calcule naturellement.
**Scénarios :**
- Plusieurs scénarios (combinaisons d'événements) peuvent coexister et être comparés.
- Les scénarios peuvent être contextualisés au client : "votre SI dépend de ces chaînes, voici votre exposition face à ce scénario".
### Pourquoi
- Les crises sont multi-causales — un seul événement isolé ne reflète pas la réalité.
- La valeur du moteur est dans la combinaison : montrer que tel produit final résiste à un événement isolé mais pas à la combinaison de deux.
- C'est un service à très forte valeur pour les clients (COMEX, DSI).
### Décisions prises
- Le point 14 est une **contrainte de conception du moteur**, pas un développement séparé. L'asservissement au bus d'impact doit être prévu dès la conception.
- Dépend du point 12 (stocks/projection temporelle) et du point 13 (bus d'impact).
---
## Ordre de réalisation logique
L'ordre des points dans ce document reflète l'ordre de la discussion, pas l'ordre de réalisation. L'analyse des dépendances donne :
L'ordre des points dans ce document reflète l'ordre de la discussion, pas l'ordre de réalisation. Le séquencement ci-dessous s'aligne sur les 4 vues architecturales présentées en fin de document.
**Phase 1 — Fondations (parallélisable) :**
### Vue 1 — Le moteur (phases 1 à 4)
Phase 1 — Fondations (parallélisable) :
- **Point 7** — Validation du modèle de niveaux (fondation théorique, prérequis au modèle de données)
- **Point 6 (spike)** — Spike technique sur 2-3 bases candidates (Neo4j Community, PostgreSQL+AGE, ArangoDB) avec un mini-graphe de test. En parallèle du point 7 car les critères de sélection (multi-graphes, schéma évolutif, requêtage, historisation, open source) sont indépendants du nombre exact de niveaux. Tests sur le serveur via Docker (16 Go RAM), installation native ensuite.
- **Point 6 (spike)** — Spike technique sur 2-3 bases candidates (Neo4j Community, PostgreSQL+AGE, ArangoDB) avec un mini-graphe de test. En parallèle du point 7.
**Phase 2 — Modèle et stockage :**
Phase 2 — Modèle et stockage :
1. **Point 3** — Modèle de données structuré (dépend des niveaux validés). Énergie et eau ne nécessitent pas de modélisation spéciale — ce sont des attributs d'opération comme les parts de marché, couverts nativement par le modèle extensible.
2. **Point 6 (implémentation)** — Mise en place du stockage retenu après le spike.
- **Point 3** — Modèle de données structuré (dépend des niveaux validés). Conçu dès le départ pour supporter les deux couches (structurel/situationnel) et l'asservissement au bus d'impact (point 14).
- **Point 6 (implémentation)** — Mise en place du stockage retenu après le spike.
**Phase 3 — Données et sources :**
Phase 3 — Données et sources :
1. **Point 2** — Gestion des sources (peut démarrer en parallèle dès la phase 2 pour l'identification/catégorisation)
2. **Point 4** — Amorçage et qualification sur un échantillon représentatif : 3 minerais + 1 composant + 1 produit final (couvre tous les niveaux du graphe). Puis audit d'exhaustivité des minerais après l'amorçage.
- **Point 2** — Gestion des sources (peut démarrer en parallèle dès la phase 2 pour l'identification/catégorisation)
- **Point 4** — Amorçage et qualification sur un échantillon représentatif : 3 minerais + 1 composant + 1 produit final. Puis audit d'exhaustivité des matières premières.
**Phase 4 — Fiches et API :**
Phase 4 — Fiches et API :
1. **Point 5** — Templates et génération des fiches
2. **Point 1** — API REST et rôles
3. **Point 8** — Services, sécurisation, profils (sous-spécification dédiée pour la personnalisation client)
- **Point 5** — Templates et génération des fiches
- **Point 1** — API REST et rôles
- **Point 8** — Services, sécurisation, profils
*Horizon (l'architecture doit les rendre possibles sans les implémenter d'emblée) :*
### Vue 2 — Veille sur les sources et propagation
- **Point 2 (veille)** — Activation de la veille sur les sources (huginn), vérification des citations. Cycle structurel trimestriel.
- **Propagation d'impact** — Le moteur gagne la capacité de simulation manuelle ("que se passe-t-il si ce nœud est coupé ?").
### Vue 3 — Veille stratégique 360°
- **Intégration écosystème 360°** — La veille stratégique se connecte sur deux points : requête l'API et propose des sources (validées par l'expert avant intégration).
### Vue 4 — Architecture complète
- **Point 11** — Granularité géographique fine (prérequis à la précision du bus d'impact)
- **Point 10** — Ressources transversales (énergie, eau)
- **Point 11** — Granularité géographique fine
- **Point 9** — Multi-sectoriel
- **Point 12** — Stocks et projection temporelle
- **Point 13** — Bus d'impact (traducteur d'événements → impacts chiffrés, IA assistée, mémoire situationnelle). Scission de la base en graphe structurel / graphe situationnel.
- **Point 14** — Combinatoire multi-impacts (native si le moteur est asservi au bus dès la conception)
- **Point 9** — Multi-sectoriel (le plus lointain)
## MVP (jalon interne)
**Définition** : moteur fonctionnel avec données réelles dans une vraie base, requêtable, données sourcées avec indice de fiabilité. Pas de frontend, pas de produit fini — un jalon de validation interne.
**Périmètre** : phases 1 + 2 + 3 (validation niveaux → spike techno → modèle de données → base → amorçage 3 minerais + 1 composant + 1 produit final).
**Périmètre** : Vue 1 complète (points 7 → 6 → 3 → 2 → 4 → 5 → 1 → 8 : validation niveaux → spike techno → modèle de données → base → amorçage 3 minerais + 1 composant + 1 produit final → fiches → API).
**Critère de succès** : on peut requêter la base et retrouver les mêmes analyses qu'aujourd'hui (ex : Sankey du germanium), avec des données sourcées et un indice de fiabilité.
**Rétro-analyse** : valider les indices sur des crises passées (Spruce Pine, quotas chinois) comme preuve de concept.
**Tests** : toute logique métier est testée (calculs d'indices, requêtage, arbitrage des sources, import/export). Pas de seuil de couverture arbitraire — on teste ce qui compte.
\newpage
## Progression architecturale
L'architecture de FabNum v2 se construit par étapes. Chaque vue ajoute un bloc fonctionnel sans remettre en cause les précédents.
### Vue 1 — Le moteur
Le socle : un moteur d'analyse requêtable via API, alimenté par des sources externes qualifiées. L'administrateur gère le graphe par scripts, les experts et clients consomment via l'API.
![Vue 1 — Le moteur](architecture-vue1.png){ width=100% }
\newpage
### Vue 2 — Veille sur les sources et propagation d'impact
Les sources ne sont plus statiques — elles sont surveillées en continu (huginn). Le moteur gagne la capacité de **propagation d'impact** : l'expert peut simuler manuellement "que se passe-t-il si ce nœud est coupé ?" et observer la propagation dans le graphe. Les clients peuvent contextualiser leurs requêtes.
![Vue 2 — Veille et propagation](architecture-vue2.png){ width=100% }
\newpage
### Vue 3 — Veille stratégique 360°
Le monde extérieur interagit avec FabNum. L'écosystème de veille 360° se connecte sur deux points : il **requête l'API** pour obtenir des analyses et il **propose des sources** qui sont validées par l'expert avant intégration.
![Vue 3 — Veille 360°](architecture-vue3.png){ width=100% }
\newpage
### Vue 4 — Architecture complète (bus d'impact, mémoire situationnelle, IA)
Le **bus d'impact** traduit les événements du monde réel en impacts chiffrés sur le graphe, assisté par l'IA et validé par l'expert. Il maintient une **mémoire situationnelle** : le graphe reflète en permanence la situation mondiale réelle. La base de données se scinde en **graphe structurel** (capacités nominales, trimestriel) et **graphe situationnel** (capacités réelles avec impacts, continu). Les indices se calculent sur les deux couches.
![Vue 4 — Architecture complète](architecture-vue4.png){ width=100% }
\newpage
## Diagramme d'Architecture Fonctionnelle (DAF)
![Macro-DAF](macro-daf.png){ height=75% }
\newpage
## Diagramme d'Architecture Technique (DAT)
![Macro-DAT](macro-dat.png){ width=100% }

Binary file not shown.

View File

@ -0,0 +1,166 @@
digraph architecture_fabnum {
// Configuration générale
rankdir=TB;
fontname="Arial";
fontsize=18;
label="FabNum — Architecture globale\n\n";
labelloc=t;
splines=true;
nodesep=0.7;
ranksep=0.9;
node [fontname="Arial", fontsize=11, style="filled,rounded", shape=box, penwidth=1.5];
edge [fontname="Arial", fontsize=9, penwidth=1.2];
// ==================== UTILISATEURS ====================
admin [
label="Administrateur\n\nGère le graphe structurel,\nles sources, les tiers\nde confiance, les arbitrages"
fillcolor="#FFE082"
shape=house
fontsize=10
];
expert [
label="Expert\n\nAnalyse les risques,\nqualifie les données,\nvalide les impacts"
fillcolor="#A5D6A7"
shape=house
fontsize=10
];
client [
label="Client\n(COMEX, Métiers, DSI)\n\nConsulte les analyses,\nles fiches, les alertes.\nPeut contextualiser\nses requêtes."
fillcolor="#EF9A9A"
shape=house
fontsize=10
];
// ==================== ÉCOSYSTÈME / VEILLE 360° ====================
ecosysteme [
label="Écosystème\nveille 360°\n\nDétecte les événements,\nalimente les sources\net le bus d'impact"
fillcolor="#CE93D8"
shape=house
fontsize=10
];
// ==================== API ====================
api [
label="API\n\nPoint d'accès unique\nAuthentification, rôles,\nprofils de visibilité\n\nSert le graphe situationnel\n(structurel accessible aussi)"
fillcolor="#B39DDB"
fontsize=11
penwidth=2
];
// ==================== BUS D'IMPACT ====================
bus [
label="Bus d'impact\n\nMémoire situationnelle\nTraduction événements → impacts\nAccumule, met à jour, archive\nMise à jour en continu\n(rythme décisionnel)"
fillcolor="#FF8A65"
fontsize=11
penwidth=2.5
style="filled,rounded,bold"
];
ia_bus [
label="IA\n\nAnalyse les événements,\npropose les impacts\nchiffrés"
fillcolor="#FFCC80"
fontsize=10
];
// ==================== MOTEUR ====================
moteur [
label="Moteur FabNum\n\nCalcul des indices\n(structurels et situationnels)\nRequêtage, chemins critiques\nGénération fiches (templates)\nArbitrage sources\nProjection temporelle"
fillcolor="#90CAF9"
fontsize=11
penwidth=2
];
// ==================== BASE DE DONNÉES ====================
subgraph cluster_bdd {
label="Base de données (graphe)";
style=filled;
color="#E0F2F1";
fontsize=11;
fontcolor="#00695C";
bdd_struct [
label="Graphe structurel\n\nCapacités nominales\nActeurs, pays, parts de marché\nIndices structurels\nMise à jour trimestrielle"
fillcolor="#80CBC4"
fontsize=10
];
bdd_situa [
label="Graphe situationnel\n\nImpacts actifs\nCapacités réelles\nIndices situationnels\nHistorique des situations"
fillcolor="#4DB6AC"
fontsize=10
];
}
// ==================== VEILLE SUR LES SOURCES ====================
veille [
label="Veille sources\n\nSurveillance des sources (huginn)\nVérification des citations\nAlertes (variations)"
fillcolor="#FFAB91"
fontsize=10
penwidth=1.5
];
// ==================== SOURCES ====================
sources [
label="Sources externes\n\nUSGS, Statista, BRGM,\nScholar Gateway, Consensus,\nWRI Aqueduct, ND-GAIN..."
fillcolor="#E0E0E0"
shape=cylinder
fontsize=10
];
// ==================== DISPOSITION ====================
{ rank=same; admin; expert; client; ecosysteme; }
{ rank=same; bus; api; }
{ rank=same; ia_bus; moteur; }
// ==================== RELATIONS ====================
// Expert → API + validation impacts
expert -> api [label="consulte\nanalyse", color="#2E7D32"];
expert -> bus [label="valide\nles impacts", color="#E65100", style=bold];
// Client → API
client -> api [label="consulte\nles résultats", color="#C62828"];
// Écosystème → Bus d'impact + Sources
ecosysteme -> bus [label="injecte\ndes événements", color="#6A1B9A", penwidth=2];
ecosysteme -> sources [label="alimente\nles sources", color="#6A1B9A", style=dashed];
// Admin → Moteur (accès direct par scripts)
admin -> moteur [label="administre\n(scripts)", color="#E65100", style=bold, penwidth=2];
// IA ↔ Bus
bus -> ia_bus [label="événement\nà analyser", color="#E65100", dir=both];
// Bus → Moteur (impacts chiffrés)
bus -> moteur [label="impacts\nchiffrés", color="#BF360C", penwidth=2];
// API ↔ Moteur
api -> moteur [label="transmet\nles requêtes", color="#4527A0", dir=both];
// Moteur ↔ Base de données
moteur -> bdd_struct [label="lit/écrit\nstructurel", color="#00695C", dir=both];
moteur -> bdd_situa [label="lit/écrit\nsituationnel", color="#00695C", dir=both];
// Bus → BDD situationnel
bus -> bdd_situa [label="met à jour\nles impacts", color="#BF360C", style=dashed];
// Veille → Sources
sources -> veille [label="surveille\nles MAJ", color="#BF360C"];
// Veille → BDD structurel
veille -> bdd_struct [label="met à jour\nles sources", color="#E65100", style=dashed];
// Sources → BDD structurel
sources -> bdd_struct [label="alimente\nles données", color="#546E7A", style=dashed];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 KiB

View File

@ -0,0 +1,73 @@
digraph architecture_vue1 {
rankdir=TB;
fontname="Arial";
fontsize=18;
label="FabNum — Vue 1 : Le moteur\nRequêtage, indices, fiches via API\n";
labelloc=t;
splines=true;
nodesep=0.7;
ranksep=0.9;
node [fontname="Arial", fontsize=10, style="filled,rounded", shape=box, penwidth=1.5];
edge [fontname="Arial", fontsize=9, penwidth=1.2];
// Ligne 1 : utilisateurs (4 colonnes fixes)
admin [
label="Administrateur\n\nGère le graphe,\nles sources, les tiers\nde confiance"
fillcolor="#FFE082" shape=house
];
expert [
label="Expert\n\nAnalyse les risques,\nqualifie les données"
fillcolor="#A5D6A7" shape=house
];
client [
label="Client\n(COMEX, Métiers, DSI)\n\nConsulte les analyses,\nles fiches, les alertes."
fillcolor="#EF9A9A" shape=house
];
// Placeholder veille 360° (invisible)
ph_eco [label="" shape=point width=0.01 style=invis];
{ rank=same; admin; expert; client; ph_eco; }
// Ligne 2 : API + placeholder bus
api [
label="API\n\nPoint d'accès unique\nAuthentification, rôles,\nprofils de visibilité"
fillcolor="#B39DDB" penwidth=2
];
// Placeholder bus (invisible)
ph_bus [label="" shape=point width=0.01 style=invis];
{ rank=same; api; ph_bus; }
// Ligne 3 : Moteur + placeholders
moteur [
label="Moteur FabNum\n\nCalcul des indices\n(IHH, ICS, IVC, ISG)\nRequêtage du graphe\nChemins critiques\nGénération fiches (templates)\nArbitrage des sources"
fillcolor="#90CAF9" penwidth=2
];
// Placeholder IA (invisible)
ph_ia [label="" shape=point width=0.01 style=invis];
// Placeholder veille (invisible)
ph_veille [label="" shape=point width=0.01 style=invis];
{ rank=same; ph_veille; moteur; ph_ia; }
// Ligne 4 : BDD + sources
bdd [
label="Base de données\n(graphe)\n\nNœuds, relations, indices\nSources rattachées\nHistorique des données"
fillcolor="#80CBC4" penwidth=2
];
sources [
label="Sources externes\n\nUSGS, Statista, BRGM,\nScholar Gateway, Consensus,\nWRI Aqueduct, ND-GAIN..."
fillcolor="#E0E0E0" shape=cylinder
];
{ rank=same; bdd; sources; }
// Relations
expert -> api [label="consulte\nanalyse", color="#2E7D32"];
client -> api [label="consulte\nles résultats", color="#C62828"];
admin -> moteur [label="administre\n(scripts)", color="#E65100", style=bold, penwidth=2];
api -> moteur [label="transmet\nles requêtes", color="#4527A0", dir=both];
moteur -> bdd [label="lit et écrit\nles données", color="#00695C", dir=both];
sources -> bdd [label="alimente\nles données", color="#546E7A", style=dashed];
// Liens invisibles pour stabiliser la disposition
ph_eco -> ph_bus [style=invis];
ph_bus -> ph_ia [style=invis];
ph_veille -> bdd [style=invis];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

View File

@ -0,0 +1,77 @@
digraph architecture_vue2 {
rankdir=TB;
fontname="Arial";
fontsize=18;
label="FabNum — Vue 2 : Veille sur les sources et propagation\nSources surveillées, simulation d'impact manuelle\n";
labelloc=t;
splines=true;
nodesep=0.7;
ranksep=0.9;
node [fontname="Arial", fontsize=10, style="filled,rounded", shape=box, penwidth=1.5];
edge [fontname="Arial", fontsize=9, penwidth=1.2];
// Ligne 1 : utilisateurs (4 colonnes fixes)
admin [
label="Administrateur\n\nGère le graphe,\nles sources, les tiers\nde confiance"
fillcolor="#FFE082" shape=house
];
expert [
label="Expert\n\nAnalyse les risques,\nqualifie les données,\nsimule des scénarios\nd'impact (propagation),\ncontextualise"
fillcolor="#A5D6A7" shape=house
];
client [
label="Client\n(COMEX, Métiers, DSI)\n\nConsulte les analyses,\nles fiches, les alertes.\nPeut contextualiser\nses requêtes."
fillcolor="#EF9A9A" shape=house
];
// Placeholder veille 360° (invisible)
ph_eco [label="" shape=point width=0.01 style=invis];
{ rank=same; admin; expert; client; ph_eco; }
// Ligne 2 : API + placeholder bus
api [
label="API\n\nPoint d'accès unique\nAuthentification, rôles,\nprofils de visibilité"
fillcolor="#B39DDB" penwidth=2
];
// Placeholder bus (invisible)
ph_bus [label="" shape=point width=0.01 style=invis];
{ rank=same; api; ph_bus; }
// Ligne 3 : Moteur + placeholder IA + veille
moteur [
label="Moteur FabNum\n\nCalcul des indices\n(IHH, ICS, IVC, ISG)\nRequêtage du graphe\nChemins critiques\nGénération fiches (templates)\nArbitrage des sources\nPropagation d'impact\n(simulation manuelle)"
fillcolor="#90CAF9" penwidth=2
];
// Placeholder IA (invisible)
ph_ia [label="" shape=point width=0.01 style=invis];
veille [
label="Veille sources\n\nSurveillance des sources\n(huginn)\nVérification des citations\nAlertes (variations)"
fillcolor="#FFAB91" penwidth=1.5
];
{ rank=same; veille; moteur; ph_ia; }
// Ligne 4 : BDD + sources
bdd [
label="Base de données\n(graphe)\n\nNœuds, relations, indices\nSources rattachées\nHistorique des données"
fillcolor="#80CBC4" penwidth=2
];
sources [
label="Sources externes\n\nUSGS, Statista, BRGM,\nScholar Gateway, Consensus,\nWRI Aqueduct, ND-GAIN..."
fillcolor="#E0E0E0" shape=cylinder
];
{ rank=same; bdd; sources; }
// Relations
expert -> api [label="consulte, analyse\net simule", color="#2E7D32"];
client -> api [label="consulte\nles résultats", color="#C62828"];
admin -> moteur [label="administre\n(scripts)", color="#E65100", style=bold, penwidth=2];
api -> moteur [label="transmet\nles requêtes", color="#4527A0", dir=both];
moteur -> bdd [label="lit et écrit\nles données", color="#00695C", dir=both];
sources -> veille [label="surveille\nles MAJ", color="#BF360C"];
veille -> bdd [label="met à jour\nles sources", color="#E65100", style=dashed];
veille -> moteur [label="signale les\nchangements\net vérifie\nles citations", color="#E65100"];
sources -> bdd [label="alimente\nles données", color="#546E7A", style=dashed];
// Liens invisibles pour stabiliser
ph_eco -> ph_bus [style=invis];
ph_bus -> ph_ia [style=invis];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

View File

@ -0,0 +1,89 @@
digraph architecture_vue3 {
rankdir=TB;
fontname="Arial";
fontsize=18;
label="FabNum — Vue 3 : Veille stratégique 360°\nLe monde extérieur interagit avec FabNum\n";
labelloc=t;
splines=true;
nodesep=0.7;
ranksep=0.9;
node [fontname="Arial", fontsize=10, style="filled,rounded", shape=box, penwidth=1.5];
edge [fontname="Arial", fontsize=9, penwidth=1.2];
// Ligne 1 : utilisateurs (4 colonnes fixes)
admin [
label="Administrateur\n\nGère le graphe,\nles sources, les tiers\nde confiance"
fillcolor="#FFE082" shape=house
];
expert [
label="Expert\n\nAnalyse les risques,\nqualifie les données,\nsimule des scénarios\nd'impact,\nvalide les sources"
fillcolor="#A5D6A7" shape=house
];
client [
label="Client\n(COMEX, Métiers, DSI)\n\nConsulte les analyses,\nles fiches, les alertes.\nPeut contextualiser\nses requêtes."
fillcolor="#EF9A9A" shape=house
];
ecosysteme [
label="Écosystème\nveille 360°\n\nDétecte les événements,\npropose des sources,\nrequête FabNum"
fillcolor="#CE93D8" shape=house
];
{ rank=same; admin; expert; client; ecosysteme; }
// Ligne 2 : API + placeholder bus
api [
label="API\n\nPoint d'accès unique\nAuthentification, rôles,\nprofils de visibilité"
fillcolor="#B39DDB" penwidth=2
];
// Placeholder bus (invisible)
ph_bus [label="" shape=point width=0.01 style=invis];
{ rank=same; api; ph_bus; }
// Ligne 3 : Moteur + placeholder IA + veille
moteur [
label="Moteur FabNum\n\nCalcul des indices\n(IHH, ICS, IVC, ISG)\nRequêtage du graphe\nChemins critiques\nGénération fiches (templates)\nArbitrage des sources\nPropagation d'impact"
fillcolor="#90CAF9" penwidth=2
];
// Placeholder IA (invisible)
ph_ia [label="" shape=point width=0.01 style=invis];
veille [
label="Veille sources\n\nSurveillance des sources\n(huginn)\nVérification des citations\nAlertes (variations)"
fillcolor="#FFAB91" penwidth=1.5
];
{ rank=same; veille; moteur; ph_ia; }
// Ligne 4 : BDD + sources
bdd [
label="Base de données\n(graphe)\n\nNœuds, relations, indices\nSources rattachées\nHistorique des données"
fillcolor="#80CBC4" penwidth=2
];
sources [
label="Sources externes\n\nUSGS, Statista, BRGM,\nScholar Gateway, Consensus,\nWRI Aqueduct, ND-GAIN..."
fillcolor="#E0E0E0" shape=cylinder
];
{ rank=same; bdd; sources; }
// Relations utilisateurs
expert -> api [label="consulte, analyse\net simule", color="#2E7D32"];
client -> api [label="consulte\nles résultats", color="#C62828"];
admin -> moteur [label="administre\n(scripts)", color="#E65100", style=bold, penwidth=2];
// Écosystème 360° — deux points d'interaction
ecosysteme -> api [label="requête\nanalyses", color="#6A1B9A", penwidth=2];
ecosysteme -> expert [label="propose\ndes sources", color="#6A1B9A", style=dashed, penwidth=2];
expert -> sources [label="valide et\nalimente", color="#2E7D32", style=bold];
// API ↔ Moteur
api -> moteur [label="transmet\nles requêtes", color="#4527A0", dir=both];
// Moteur ↔ BDD
moteur -> bdd [label="lit et écrit\nles données", color="#00695C", dir=both];
// Veille
sources -> veille [label="surveille\nles MAJ", color="#BF360C"];
veille -> bdd [label="met à jour\nles sources", color="#E65100", style=dashed];
veille -> moteur [label="signale les\nchangements\net vérifie\nles citations", color="#E65100"];
sources -> bdd [label="alimente\nles données", color="#546E7A", style=dashed];
// Liens invisibles pour stabiliser
ph_bus -> ph_ia [style=invis];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 KiB

View File

@ -0,0 +1,113 @@
digraph architecture_vue4 {
rankdir=TB;
fontname="Arial";
fontsize=18;
label="FabNum — Vue 4 : Architecture complète\nBus d'impact, mémoire situationnelle, IA\n";
labelloc=t;
splines=true;
nodesep=0.7;
ranksep=0.9;
node [fontname="Arial", fontsize=10, style="filled,rounded", shape=box, penwidth=1.5];
edge [fontname="Arial", fontsize=9, penwidth=1.2];
// Ligne 1 : utilisateurs (4 colonnes fixes)
admin [
label="Administrateur\n\nGère le graphe structurel,\nles sources, les tiers\nde confiance"
fillcolor="#FFE082" shape=house
];
expert [
label="Expert\n\nAnalyse les risques,\nqualifie les données,\nvalide les impacts,\nvalide les sources"
fillcolor="#A5D6A7" shape=house
];
client [
label="Client\n(COMEX, Métiers, DSI)\n\nConsulte les analyses,\nles fiches, les alertes.\nPeut contextualiser\nses requêtes."
fillcolor="#EF9A9A" shape=house
];
ecosysteme [
label="Écosystème\nveille 360°\n\nDétecte les événements,\npropose des sources,\nalimente le bus d'impact"
fillcolor="#CE93D8" shape=house
];
{ rank=same; admin; expert; client; ecosysteme; }
// Ligne 2 : API + Bus d'impact
api [
label="API\n\nPoint d'accès unique\nAuthentification, rôles,\nprofils de visibilité\n\nSert le graphe situationnel\n(structurel accessible aussi)"
fillcolor="#B39DDB" penwidth=2
];
bus [
label="Bus d'impact\n\nMémoire situationnelle\nTraduction événements → impacts\nAccumule, met à jour, archive\nMise à jour en continu\n(rythme décisionnel)"
fillcolor="#FF8A65" penwidth=2.5
style="filled,rounded,bold"
];
{ rank=same; api; bus; }
// Ligne 3 : Moteur + IA + veille
moteur [
label="Moteur FabNum\n\nCalcul des indices\n(structurels et situationnels)\nRequêtage, chemins critiques\nGénération fiches (templates)\nArbitrage des sources\nProjection temporelle"
fillcolor="#90CAF9" penwidth=2
];
ia_bus [
label="IA\n\nAnalyse les événements,\npropose les impacts\nchiffrés"
fillcolor="#FFCC80"
];
veille [
label="Veille sources\n\nSurveillance des sources\n(huginn)\nVérification des citations\nAlertes (variations)"
fillcolor="#FFAB91" penwidth=1.5
];
{ rank=same; veille; moteur; ia_bus; }
// Ligne 4 : BDD scindée + sources
subgraph cluster_bdd {
label="Base de données (graphe)";
style=filled;
color="#E0F2F1";
fontsize=10;
fontcolor="#00695C";
bdd_situa [
label="Graphe situationnel\n\nImpacts actifs\nCapacités réelles\nIndices situationnels\nHistorique des situations"
fillcolor="#4DB6AC"
];
bdd_struct [
label="Graphe structurel\n\nCapacités nominales\nActeurs, pays, parts de marché\nIndices structurels\nMise à jour trimestrielle"
fillcolor="#80CBC4"
];
}
sources [
label="Sources externes\n\nUSGS, Statista, BRGM,\nScholar Gateway, Consensus,\nWRI Aqueduct, ND-GAIN..."
fillcolor="#E0E0E0" shape=cylinder
];
// Relations utilisateurs
expert -> api [label="consulte\nanalyse", color="#2E7D32"];
expert -> sources [label="valide et\nalimente", color="#2E7D32", style=bold];
client -> api [label="consulte\nles résultats", color="#C62828"];
admin -> moteur [label="administre\n(scripts)", color="#E65100", style=bold, penwidth=2];
// Écosystème 360° — trois interactions
ecosysteme -> api [label="requête\nanalyses", color="#6A1B9A"];
ecosysteme -> expert [label="propose événements\net sources", color="#6A1B9A", style=dashed, penwidth=2];
// Expert → Bus (événements validés)
expert -> bus [label="valide\nles impacts", color="#E65100", style=bold];
// Bus ↔ IA
bus -> ia_bus [label="événement\nà analyser", color="#E65100", dir=both];
// Bus → Moteur + BDD (deux sorties)
bus -> moteur [label="impacts\nchiffrés", color="#BF360C", penwidth=2];
bus -> bdd_situa [label="MAJ\nsituationnel", color="#BF360C", style=dashed];
bus -> bdd_struct [label="MAJ structurel\n(fermeture mine,\nnouvel opérateur)", color="#BF360C", style=dashed];
// API ↔ Moteur
api -> moteur [label="transmet\nles requêtes", color="#4527A0", dir=both];
// Moteur ↔ BDD
moteur -> bdd_struct [label="lit/écrit\nstructurel", color="#00695C", dir=both];
moteur -> bdd_situa [label="lit/écrit\nsituationnel", color="#00695C", dir=both];
// Veille
sources -> veille [label="surveille\nles MAJ", color="#BF360C"];
veille -> bdd_struct [label="met à jour\nles sources", color="#E65100", style=dashed];
sources -> bdd_struct [label="alimente\nles données", color="#546E7A", style=dashed];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

View File

@ -1,14 +1,14 @@
digraph macro_daf {
rankdir=TB;
fontname="Arial";
node [fontname="Arial", fontsize=10, style=filled, shape=record];
node [fontname="Arial", fontsize=10, style=filled, shape=box];
edge [fontname="Arial", fontsize=9];
label="FabNum — Macro-DAF (Diagramme d'Activités Fonctionnel)\n\n";
label="FabNum — Macro-DAF (Dossier d'Architecture Fonctionnel)\n\n";
labelloc=t;
fontsize=16;
compound=true;
// Fonctions métier — flux principal
// F1. Modéliser
subgraph cluster_F1 {
label="F1. MODÉLISER LA CHAÎNE DE VALEUR";
style=filled; color="#E3F2FD"; fontsize=12; fontcolor="#1565C0";
@ -16,12 +16,14 @@ digraph macro_daf {
F1_1 [label="F1.1\nValider les niveaux\nde décomposition", fillcolor="#BBDEFB"];
F1_2 [label="F1.2\nDéfinir les intitulés\ngénériques", fillcolor="#BBDEFB"];
F1_3 [label="F1.3\nDéfinir les critères\nd'arrêt (profondeur)", fillcolor="#BBDEFB"];
F1_4 [label="F1.4\nGérer chaînes\nprincipales / connexes", fillcolor="#BBDEFB"];
F1_4 [label="F1.4\nGérer chaînes\nessentielles / connexes", fillcolor="#BBDEFB"];
F1_5 [label="F1.5\nGérer les matières\ncomposées (NMC...)", fillcolor="#BBDEFB"];
F1_1 -> F1_2 -> F1_3 -> F1_4;
F1_1 -> F1_2 -> F1_3 -> F1_4 -> F1_5;
acteur_F1 [label="Acteur : Admin", shape=ellipse, fillcolor="#E3F2FD", fontsize=9];
}
// F2. Structurer et qualifier
subgraph cluster_F2 {
label="F2. STRUCTURER ET QUALIFIER LES DONNÉES";
style=filled; color="#E8F5E9"; fontsize=12; fontcolor="#2E7D32";
@ -29,56 +31,61 @@ digraph macro_daf {
F2_1 [label="F2.1\nSpécifier données\n(essentielles / info)", fillcolor="#C8E6C9"];
F2_2 [label="F2.2\nDéfinir périmètre\nmesuré", fillcolor="#C8E6C9"];
F2_3 [label="F2.3\nIdentifier et catégoriser\nles sources", fillcolor="#C8E6C9"];
F2_4 [label="F2.4\nAttribuer tiers\nde confiance", fillcolor="#C8E6C9"];
F2_4 [label="F2.4\nAttribuer tiers\nde confiance\n(par domaine)", fillcolor="#C8E6C9"];
F2_5 [label="F2.5\nQualifier données\n(filtres qualité)", fillcolor="#C8E6C9"];
F2_6 [label="F2.6\nArbitrer divergences\nentre sources", fillcolor="#C8E6C9"];
F2_6 [label="F2.6\nArbitrer divergences\n(tier 1 par défaut,\nconvergence → alerte)", fillcolor="#C8E6C9"];
F2_7 [label="F2.7\nCalculer indice\nde fiabilité", fillcolor="#C8E6C9"];
F2_1 -> F2_2 -> F2_3 -> F2_4 -> F2_5 -> F2_6 -> F2_7;
acteur_F2 [label="Acteur : Admin", shape=ellipse, fillcolor="#E8F5E9", fontsize=9];
}
// F3. Surveiller et maintenir
subgraph cluster_F3 {
label="F3. SURVEILLER ET MAINTENIR";
label="F3. SURVEILLER ET MAINTENIR (cycle structurel — trimestriel)";
style=filled; color="#FFF3E0"; fontsize=12; fontcolor="#E65100";
F3_1 [label="F3.1\nVeiller sur\nles sources\n(huginn)", fillcolor="#FFE0B2"];
F3_2 [label="F3.2\nDétecter variations\nanormales (alertes)", fillcolor="#FFE0B2"];
F3_3 [label="F3.3\nContrôler\ncitations", fillcolor="#FFE0B2"];
F3_3 [label="F3.3\nContrôler\ncitations\n(verify-citations)", fillcolor="#FFE0B2"];
F3_4 [label="F3.4\nHistoriser données\net indices", fillcolor="#FFE0B2"];
F3_5 [label="F3.5\nAuditer exhaustivité\ndes minerais", fillcolor="#FFE0B2"];
F3_5 [label="F3.5\nAuditer exhaustivité\ndes matières premières", fillcolor="#FFE0B2"];
F3_1 -> F3_2;
F3_3 -> F3_4;
acteur_F3 [label="Acteurs : Admin (gouv.)\nServices internes (auto.)", shape=ellipse, fillcolor="#FFF3E0", fontsize=9];
}
// F4. Calculer les indices
subgraph cluster_F4 {
label="F4. CALCULER LES INDICES DE CRITICITÉ";
style=filled; color="#FCE4EC"; fontsize=12; fontcolor="#C62828";
F4_1 [label="F4.1\nCalculer IHH, ICS\nIVC, ISG\n(+ futurs)", fillcolor="#F8BBD0"];
F4_1 [label="F4.1\nCalculer IHH, ICS\nIVC, ISG (+ futurs)\nstructurels et situationnels", fillcolor="#F8BBD0"];
F4_2 [label="F4.2\nPré-calculer à\nchaque MAJ graphe", fillcolor="#F8BBD0"];
F4_3 [label="F4.3\nMéta-indices\ndynamiques\n(sur sélection)", fillcolor="#F8BBD0"];
F4_4 [label="F4.4\nRétro-analyser\n(backtesting)", fillcolor="#F8BBD0"];
F4_5 [label="F4.5\nPropager les impacts\net projeter\ntemporellement", fillcolor="#F8BBD0"];
F4_1 -> F4_2;
F4_3 -> F4_4 [style=dashed];
F4_3 -> F4_4;
acteur_F4 [label="Acteur : Services internes", shape=ellipse, fillcolor="#FCE4EC", fontsize=9];
}
// F5. Produire les fiches
subgraph cluster_F5 {
label="F5. PRODUIRE LES FICHES";
style=filled; color="#F3E5F5"; fontsize=12; fontcolor="#6A1B9A";
F5_1 [label="F5.1\nGénérer depuis\ndonnées via templates", fillcolor="#E1BEE7"];
F5_2 [label="F5.2\nAdapter par niveau\n(minerai, composant...)", fillcolor="#E1BEE7"];
F5_2 [label="F5.2\nAdapter par niveau\n(matière première,\ncomposant, composé...)", fillcolor="#E1BEE7"];
F5_3 [label="F5.3\nAdapter par usage\n(expertise, synthèse,\nAPI/JSON)", fillcolor="#E1BEE7"];
F5_1 -> F5_2 -> F5_3;
acteur_F5 [label="Acteur : Services internes", shape=ellipse, fillcolor="#F3E5F5", fontsize=9];
}
// F6. Exposer et servir
subgraph cluster_F6 {
label="F6. EXPOSER ET SERVIR";
style=filled; color="#E0F2F1"; fontsize=12; fontcolor="#00695C";
@ -87,29 +94,44 @@ digraph macro_daf {
F6_2 [label="F6.2\nConsultation\nfiches", fillcolor="#B2DFDB"];
F6_3 [label="F6.3\nAnalyse vulnérabilité\net scénarios", fillcolor="#B2DFDB"];
F6_4 [label="F6.4\nExport\n(PDF, JSON, DOT)", fillcolor="#B2DFDB"];
F6_5 [label="F6.5\nPersonnalisation\nclient (projection SI)", fillcolor="#B2DFDB"];
F6_5 [label="F6.5\nContextualisation\nclient", fillcolor="#B2DFDB"];
F6_6 [label="F6.6\nIntégration\nécosystème 360°", fillcolor="#B2DFDB"];
F6_7 [label="F6.7\nScénarios multi-impacts\n(combinatoire)", fillcolor="#B2DFDB"];
acteur_F6 [label="Acteurs : Expert, Service\nCOMEX, Métiers, DSAI", shape=ellipse, fillcolor="#E0F2F1", fontsize=9];
acteur_F6 [label="Acteurs : Expert, Client\nCOMEX, Métiers, DSI", shape=ellipse, fillcolor="#E0F2F1", fontsize=9];
}
// Transversal
// F7. Capter et traduire les événements
subgraph cluster_F7 {
label="F7. SÉCURISER ET CONTRÔLER (transversal)";
label="F7. CAPTER ET TRADUIRE LES ÉVÉNEMENTS (bus d'impact)";
style=filled; color="#FBE9E7"; fontsize=12; fontcolor="#BF360C";
F7_1 [label="F7.1\nRecevoir événements\n(veille 360°,\nsignaux faibles)", fillcolor="#FFCCBC"];
F7_2 [label="F7.2\nTraduire en impacts\nchiffrés (IA)", fillcolor="#FFCCBC"];
F7_3 [label="F7.3\nValidation expert\navant injection", fillcolor="#FFCCBC"];
F7_4 [label="F7.4\nMaintenir la mémoire\nsituationnelle\n(accumule, archive)", fillcolor="#FFCCBC"];
F7_5 [label="F7.5\nMettre à jour\nle graphe situationnel", fillcolor="#FFCCBC"];
F7_1 -> F7_2 -> F7_3 -> F7_4 -> F7_5;
acteur_F7 [label="Acteurs : Veille 360° (input)\nIA (traduction)\nExpert (validation)", shape=ellipse, fillcolor="#FBE9E7", fontsize=9];
}
// F8. Sécuriser et contrôler (transversal)
subgraph cluster_F8 {
label="F8. SÉCURISER ET CONTRÔLER (transversal)";
style=filled; color="#ECEFF1"; fontsize=12; fontcolor="#37474F";
F7_1 [label="F7.1 Auth\n(user / API key)", fillcolor="#CFD8DC"];
F7_2 [label="F7.2 Rôles\n(admin/expert/service)", fillcolor="#CFD8DC"];
F7_3 [label="F7.3 Profils\nvisibilité", fillcolor="#CFD8DC"];
F7_4 [label="F7.4 Rate\nlimiting", fillcolor="#CFD8DC"];
F7_5 [label="F7.5 Monitoring\nobservabilité", fillcolor="#CFD8DC"];
F8_1 [label="F8.1 Auth\n(user / API key)", fillcolor="#CFD8DC"];
F8_2 [label="F8.2 Rôles\n(admin/expert/service)", fillcolor="#CFD8DC"];
F8_3 [label="F8.3 Profils\nvisibilité", fillcolor="#CFD8DC"];
F8_4 [label="F8.4 Rate limiting\n+ Monitoring", fillcolor="#CFD8DC"];
F7_1 -> F7_2 -> F7_3;
acteur_F7 [label="Acteurs : Admin (config)\nSystème (exécution)", shape=ellipse, fillcolor="#ECEFF1", fontsize=9];
F8_1 -> F8_2 -> F8_3;
acteur_F8 [label="Acteurs : Admin (config)\nSystème (exécution)", shape=ellipse, fillcolor="#ECEFF1", fontsize=9];
}
// Flux principal
F1_4 -> F2_1 [lhead=cluster_F2, ltail=cluster_F1, penwidth=2, color="#333333"];
F1_5 -> F2_1 [lhead=cluster_F2, ltail=cluster_F1, penwidth=2, color="#333333"];
F2_7 -> F3_1 [lhead=cluster_F3, ltail=cluster_F2, penwidth=2, color="#333333"];
F3_4 -> F4_1 [lhead=cluster_F4, ltail=cluster_F3, penwidth=2, color="#333333"];
F4_2 -> F5_1 [lhead=cluster_F5, ltail=cluster_F4, penwidth=2, color="#333333"];
@ -118,7 +140,13 @@ digraph macro_daf {
// F3 en continu
F3_2 -> F3_1 [style=dashed, color="#E65100", label="boucle\ncontinue"];
// F7 transversal
F7_3 -> F5_1 [style=dotted, color="#37474F", lhead=cluster_F5, label="filtre"];
F7_3 -> F6_1 [style=dotted, color="#37474F", lhead=cluster_F6, label="filtre"];
// F7 alimente F4 (impacts → calcul)
F7_5 -> F4_5 [lhead=cluster_F4, ltail=cluster_F7, penwidth=2, color="#BF360C", label="impacts\nchiffrés"];
// F7 boucle situationnelle
F7_4 -> F7_1 [style=dashed, color="#BF360C", label="mise à jour\ncontinue"];
// F8 transversal
F8_3 -> F5_1 [style=dotted, color="#37474F", lhead=cluster_F5, label="filtre"];
F8_3 -> F6_1 [style=dotted, color="#37474F", lhead=cluster_F6, label="filtre"];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 KiB

View File

@ -0,0 +1,182 @@
digraph macro_dat {
rankdir=TB;
fontname="Arial";
node [fontname="Arial", fontsize=10, style="filled,rounded", shape=box, penwidth=1.5];
edge [fontname="Arial", fontsize=9, penwidth=1.2];
label="FabNum — Macro-DAT (Dossier d'Architecture Technique)\n\n";
labelloc=t;
fontsize=16;
compound=true;
// ==================== COUCHE STOCKAGE ====================
subgraph cluster_stockage {
label="COUCHE STOCKAGE";
style=filled; color="#E3F2FD"; fontsize=13; fontcolor="#1565C0";
bdd_struct [
label="Graphe structurel\n\nCapacités nominales\nActeurs, pays, parts de marché\nIndices structurels\nMise à jour trimestrielle"
fillcolor="#BBDEFB"
];
bdd_situa [
label="Graphe situationnel\n\nImpacts actifs\nCapacités réelles\nIndices situationnels\nHistorique des situations"
fillcolor="#90CAF9"
];
historisation [
label="Historisation\n\nSnapshots horodatés\nVersions données + indices\nAudit trail\nRétro-analyse"
fillcolor="#BBDEFB"
];
sources_db [
label="Référentiel sources\n\nSources catégorisées\nTiers de confiance (par domaine)\nLiens source ↔ donnée\nIndice de fiabilité"
fillcolor="#BBDEFB"
];
}
// ==================== COUCHE MOTEUR ====================
subgraph cluster_moteur {
label="COUCHE MOTEUR (Python)";
style=filled; color="#E8F5E9"; fontsize=13; fontcolor="#2E7D32";
subgraph cluster_calcul {
label="Calcul";
style=filled; color="#C8E6C9";
calcul_indices [label="Calcul indices\n\nIHH, ICS, IVC, ISG\n+ futurs (eau, énergie)\nStructurels ET situationnels\nPré-calcul à chaque MAJ", fillcolor="#A5D6A7"];
meta_indices [label="Méta-indices\n\nCalcul dynamique\nsur sous-graphe\nsélectionné", fillcolor="#A5D6A7"];
propagation [label="Propagation\nd'impact\n\nSimulation manuelle\nou via bus\nProjection temporelle\n(stocks)", fillcolor="#A5D6A7"];
}
subgraph cluster_qualite {
label="Qualité données";
style=filled; color="#C8E6C9";
arbitrage [label="Arbitrage sources\n\nTier 1 par défaut\nConvergence → alerte\nSeuils variation", fillcolor="#A5D6A7"];
qualification [label="Qualification\n\nFiltres qualité\nIndice fiabilité\nPérimètre mesuré", fillcolor="#A5D6A7"];
}
subgraph cluster_requetage {
label="Requêtage";
style=filled; color="#C8E6C9";
chemins [label="Traversée graphe\n\nChemins critiques\nFiltrage multi-critères\nSous-graphes", fillcolor="#A5D6A7"];
projection_client [label="Contextualisation\nclient\n\nMapping contexte client\nsur graphe FabNum\n(stateless)", fillcolor="#A5D6A7"];
scenarios [label="Scénarios\nmulti-impacts\n\nCombinatoire N événements\nComparaison scénarios\nContextualisé client", fillcolor="#A5D6A7"];
}
subgraph cluster_generation {
label="Génération";
style=filled; color="#C8E6C9";
templates [label="Templates fiches\n\nNiveau × usage\nExpertise / Synthèse\nAPI / JSON", fillcolor="#A5D6A7"];
import_export [label="Import / Export\n\nDOT (legacy)\nJSON\nPDF\nBackup / Restore", fillcolor="#A5D6A7"];
}
}
// ==================== BUS D'IMPACT ====================
subgraph cluster_bus {
label="BUS D'IMPACT";
style=filled; color="#FBE9E7"; fontsize=13; fontcolor="#BF360C";
memoire [
label="Mémoire situationnelle\n\nImpacts actifs\nHistorique événements\nAccumule, met à jour, archive"
fillcolor="#FFCCBC"
];
traducteur [
label="Traducteur IA\n\nÉvénement → impacts chiffrés\nNœuds impactés, % réduction\nDurée estimée"
fillcolor="#FFAB91"
];
validation [
label="Validation expert\n\nPropose → valide\nPas d'injection automatique"
fillcolor="#FFCCBC"
];
traducteur -> validation -> memoire;
}
// ==================== SERVICES INTERNES ====================
subgraph cluster_services_internes {
label="SERVICES INTERNES (non exposés)";
style=filled; color="#FFF3E0"; fontsize=13; fontcolor="#E65100";
veille [label="Veille sources\n(huginn)\n\nDétection MAJ\nNouvelles sources\nDisparitions", fillcolor="#FFE0B2"];
verif_citations [label="Vérification\ncitations\n\nverify-citations", fillcolor="#FFE0B2"];
recalcul [label="Recalcul indices\n\nDéclenché par MAJ\nstructurel + situationnel", fillcolor="#FFE0B2"];
alertes [label="Alertes\n\nVariations anormales\nConvergence sources", fillcolor="#FFE0B2"];
}
// ==================== API REST ====================
subgraph cluster_api {
label="API REST (point d'accès unique)";
style=filled; color="#F3E5F5"; fontsize=13; fontcolor="#6A1B9A";
subgraph cluster_securite {
label="Sécurité";
style=filled; color="#E1BEE7";
auth [label="Auth + Rôles\n(user / API key)", fillcolor="#CE93D8"];
profils [label="Profils visibilité", fillcolor="#CE93D8"];
rate_limit [label="Rate limiting\nMonitoring", fillcolor="#CE93D8"];
}
subgraph cluster_endpoints {
label="Endpoints";
style=filled; color="#E1BEE7";
ep_graphe [label="/graphe/*\nstructurel + situationnel", fillcolor="#CE93D8"];
ep_fiches [label="/fiches/*\ntous formats", fillcolor="#CE93D8"];
ep_analyse [label="/analyse/*\nvulnérabilités, scénarios", fillcolor="#CE93D8"];
ep_indices [label="/indices/*\nstructurels + situationnels", fillcolor="#CE93D8"];
ep_export [label="/export/*\nPDF, JSON, DOT", fillcolor="#CE93D8"];
ep_admin [label="/admin/*\nCRUD, sources", fillcolor="#CE93D8"];
}
}
// ==================== CONSOMMATEURS ====================
frontend [label="Frontend expert\n\nAnalyse, simulation,\nqualification", fillcolor="#CFD8DC", shape=house];
client_app [label="Client\n\nCOMEX, Métiers, DSI\nContextualisé", fillcolor="#CFD8DC", shape=house];
ecosysteme [label="Écosystème 360°\n\nVeille stratégique\nIRON, alertes", fillcolor="#CFD8DC", shape=house];
// Admin
admin [label="Admin (scripts)\n\nCRUD graphe structurel\nGestion sources\nTiers, arbitrage", fillcolor="#FFCC80", shape=hexagon];
// Veille 360°
veille360 [label="Veille 360°\n\nÉvénements géopolitiques\nclimatiques, économiques\nSignaux faibles", fillcolor="#CE93D8", shape=house];
// ==================== LIENS ====================
// Stockage → Moteur
bdd_struct -> chemins [color="#1565C0"];
bdd_struct -> calcul_indices [color="#1565C0"];
bdd_situa -> propagation [color="#1565C0"];
bdd_situa -> scenarios [color="#1565C0"];
sources_db -> arbitrage [color="#1565C0"];
// Bus → Stockage + Moteur
memoire -> bdd_situa [label="MAJ\nsituationnel", color="#BF360C"];
memoire -> propagation [label="impacts\nchiffrés", color="#BF360C", penwidth=2];
// Veille 360° → Bus
veille360 -> traducteur [label="événements", color="#6A1B9A", penwidth=2];
// Moteur → Services internes
calcul_indices -> recalcul [color="#E65100"];
arbitrage -> alertes [color="#E65100"];
// Moteur → API
chemins -> ep_graphe [color="#6A1B9A"];
meta_indices -> ep_indices [color="#6A1B9A"];
templates -> ep_fiches [color="#6A1B9A"];
import_export -> ep_export [color="#6A1B9A"];
propagation -> ep_analyse [color="#6A1B9A"];
scenarios -> ep_analyse [color="#6A1B9A"];
// API → Consommateurs
ep_graphe -> frontend [color="#37474F"];
ep_analyse -> frontend [color="#37474F"];
ep_fiches -> client_app [color="#37474F"];
ep_analyse -> client_app [color="#37474F"];
ep_graphe -> ecosysteme [color="#37474F"];
ep_indices -> ecosysteme [color="#37474F"];
// Admin
admin -> bdd_struct [color="#E65100", penwidth=2, label="accès\ndirect"];
// Services internes → Stockage
veille -> sources_db [color="#E65100", style=dashed, label="MAJ sources"];
recalcul -> bdd_struct [color="#E65100", style=dashed];
recalcul -> bdd_situa [color="#E65100", style=dashed];
alertes -> admin [color="#E65100", style=dashed, label="notification"];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 KiB

View File

Before

Width:  |  Height:  |  Size: 356 KiB

After

Width:  |  Height:  |  Size: 356 KiB

View File

@ -1,7 +1,7 @@
digraph planification_temporelle {
rankdir=LR;
fontname="Arial";
node [fontname="Arial", fontsize=11, style=filled, shape=record];
node [fontname="Arial", fontsize=11, style=filled, shape=box];
edge [fontname="Arial", fontsize=9];
label="FabNum — Planification temporelle\n\n";
labelloc=t;
@ -15,8 +15,8 @@ digraph planification_temporelle {
fontsize=13;
fontcolor="#1565C0";
P7 [label="P7\nValidation\nniveaux|Revue littérature\nSCOR, ISO 28000\nOpen Supply Hub", fillcolor="#BBDEFB"];
P6spike [label="P6 spike\nTest bases\ndonnées|Neo4j Community\nPostgreSQL+AGE\nArangoDB\n(Docker/serveur)", fillcolor="#BBDEFB"];
P7 [label="P7\nValidation\nniveaux\nRevue littérature\nSCOR, ISO 28000\nOpen Supply Hub", fillcolor="#BBDEFB"];
P6spike [label="P6 spike\nTest bases\ndonnées\nNeo4j Community\nPostgreSQL+AGE\nArangoDB\n(Docker/serveur)", fillcolor="#BBDEFB"];
}
subgraph cluster_phase2 {
@ -26,8 +26,8 @@ digraph planification_temporelle {
fontsize=13;
fontcolor="#2E7D32";
P3 [label="P3\nModèle de\ndonnées|Essentielles / Info\nTiers confiance\nArbitrage\nHistorisation\nIndice fiabilité", fillcolor="#C8E6C9"];
P6impl [label="P6 impl\nStockage|Base retenue\nInstallation native\nBackup", fillcolor="#C8E6C9"];
P3 [label="P3\nModèle de\ndonnées\nEssentielles / Info\nTiers confiance\nArbitrage\nHistorisation\nIndice fiabilité", fillcolor="#C8E6C9"];
P6impl [label="P6 impl\nStockage\nBase retenue\nInstallation native\nBackup", fillcolor="#C8E6C9"];
}
subgraph cluster_phase3 {
@ -37,8 +37,8 @@ digraph planification_temporelle {
fontsize=13;
fontcolor="#E65100";
P2 [label="P2\nGestion\nsources|Identification\nCatégorisation\nVeille (huginn)\nVérification citations", fillcolor="#FFE0B2"];
P4 [label="P4\nAmorçage|3 minerais\n1 composant\n1 produit final\nQualification\n+ audit exhaustivité", fillcolor="#FFE0B2"];
P2 [label="P2\nGestion\nsources\nIdentification\nCatégorisation\nVeille (huginn)\nVérification citations", fillcolor="#FFE0B2"];
P4 [label="P4\nAmorçage\n3 minerais\n1 composant\n1 produit final\nQualification\n+ audit exhaustivité", fillcolor="#FFE0B2"];
}
subgraph cluster_phase4 {
@ -48,9 +48,9 @@ digraph planification_temporelle {
fontsize=13;
fontcolor="#6A1B9A";
P5 [label="P5\nTemplates\nfiches|Niveau × usage\nExpertise\nSynthèse\nAPI/JSON", fillcolor="#E1BEE7"];
P1 [label="P1\nAPI REST\n+ rôles|Admin / Expert / Service\nAuth + tokens\nAPI-first", fillcolor="#E1BEE7"];
P8 [label="P8\nServices\nsécu profils|Personnalisation client\nProfils visibilité\nRate limiting\nRGPD / stateless", fillcolor="#E1BEE7"];
P5 [label="P5\nTemplates\nfiches\nNiveau × usage\nExpertise\nSynthèse\nAPI/JSON", fillcolor="#E1BEE7"];
P1 [label="P1\nAPI REST\n+ rôles\nAdmin / Expert / Service\nAuth + tokens\nAPI-first", fillcolor="#E1BEE7"];
P8 [label="P8\nServices\nsécu profils\nPersonnalisation client\nProfils visibilité\nRate limiting\nRGPD / stateless", fillcolor="#E1BEE7"];
}
subgraph cluster_horizon {
@ -60,13 +60,13 @@ digraph planification_temporelle {
fontsize=13;
fontcolor="#4E342E";
P10 [label="P10\nÉnergie / Eau|Attributs opération\nSourçage parcellaire\nCroisements risques", fillcolor="#D7CCC8"];
P11 [label="P11\nGéo fine|Région / site\nWRI Aqueduct\nAlertes climatiques", fillcolor="#D7CCC8"];
P9 [label="P9\nMulti-\nsectoriel|Graphes par secteur\nConnexes inter-secteurs\nMinerais partagés", fillcolor="#D7CCC8"];
P10 [label="P10\nÉnergie / Eau\nAttributs opération\nSourçage parcellaire\nCroisements risques", fillcolor="#D7CCC8"];
P11 [label="P11\nGéo fine\nRégion / site\nWRI Aqueduct\nAlertes climatiques", fillcolor="#D7CCC8"];
P9 [label="P9\nMulti-\nsectoriel\nGraphes par secteur\nConnexes inter-secteurs\nMinerais partagés", fillcolor="#D7CCC8"];
}
// MVP
MVP [label="MVP\nJalon interne|Moteur requêtable\nDonnées sourcées\nIndice fiabilité\nRétro-analyse", shape=doubleoctagon, fillcolor="#FFF9C4", style="filled,bold"];
MVP [label="MVP\nJalon interne\nMoteur requêtable\nDonnées sourcées\nIndice fiabilité\nRétro-analyse", shape=doubleoctagon, fillcolor="#FFF9C4", style="filled,bold"];
// Dépendances principales
P7 -> P3 [label="niveaux\nvalidés", color="#2E7D32", penwidth=2];

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

View File

@ -1,124 +0,0 @@
digraph architecture_fabnum {
// Configuration générale
rankdir=TB;
fontname="Arial";
fontsize=18;
label="FabNum — Architecture globale\n\n";
labelloc=t;
splines=true;
nodesep=0.8;
ranksep=1.0;
node [fontname="Arial", fontsize=12, style="filled,rounded", shape=box, penwidth=1.5];
edge [fontname="Arial", fontsize=10, penwidth=1.5];
// ==================== UTILISATEURS ====================
admin [
label="Administrateur\n\nGère le graphe, les sources,\nles tiers de confiance\net les arbitrages"
fillcolor="#FFE082"
shape=house
fontsize=11
];
expert [
label="Expert\n\nAnalyse les risques,\nqualifie les données,\nalimente la connaissance"
fillcolor="#A5D6A7"
shape=house
fontsize=11
];
client [
label="Client\n(COMEX, Métiers, DSI)\n\nConsulte les analyses,\nles fiches, les alertes.\nPeut contextualiser\nses requêtes."
fillcolor="#EF9A9A"
shape=house
fontsize=11
];
ecosysteme [
label="Écosystème\nveille 360°\n\nInterroge FabNum\net alimente\nles sources"
fillcolor="#CE93D8"
shape=house
fontsize=11
];
// ==================== API ====================
api [
label="API\n\nPoint d'accès unique\nAuthentification, rôles,\nprofils de visibilité"
fillcolor="#B39DDB"
fontsize=12
penwidth=2
];
// ==================== MOTEUR ====================
moteur [
label="Moteur FabNum\n\nCalcul des indices (IHH, ICS, IVC, ISG...)\nRequêtage du graphe, chemins critiques\nGénération des fiches (templates)\nArbitrage des sources"
fillcolor="#90CAF9"
fontsize=12
penwidth=2
];
// ==================== BASE DE DONNÉES ====================
bdd [
label="Base de données\n(graphe)\n\nNœuds, relations, indices\nSources rattachées\nHistorique des données"
fillcolor="#80CBC4"
fontsize=12
penwidth=2
];
// ==================== VEILLE ====================
veille [
label="Veille\n\nSurveillance des sources (huginn)\nVérification des citations\nAlertes (variations, événements)"
fillcolor="#FFAB91"
fontsize=12
penwidth=2
];
// ==================== SOURCES ====================
sources [
label="Sources externes\n\nUSGS, Statista, BRGM,\nScholar Gateway, Consensus,\nWRI Aqueduct, ND-GAIN..."
fillcolor="#E0E0E0"
shape=cylinder
fontsize=11
];
// ==================== DISPOSITION ====================
{ rank=same; admin; expert; client; ecosysteme; }
{ rank=same; veille; moteur; }
// ==================== RELATIONS ====================
// Expert → API
expert -> api [label="consulte\nanalyse", color="#2E7D32"];
// Client → API
client -> api [label="consulte\nles résultats", color="#C62828"];
// Écosystème ↔ API + Sources (bidirectionnel)
ecosysteme -> api [label="requête\nanalyses", color="#6A1B9A"];
ecosysteme -> sources [label="alimente\nles sources", color="#6A1B9A", style=dashed];
// Admin → Moteur (accès direct par scripts, pas via API)
admin -> moteur [label="administre\n(scripts)", color="#E65100", style=bold, penwidth=2];
// API ↔ Moteur
api -> moteur [label="transmet\nles requêtes", color="#4527A0", dir=both];
// Moteur ↔ Base de données
moteur -> bdd [label="lit et écrit\nles données", color="#00695C", dir=both];
// Veille → Sources
sources -> veille [label="surveille\nles mises à jour", color="#BF360C"];
// Veille → Moteur / BDD
veille -> moteur [label="signale les\nchangements\net vérifie\nles citations", color="#E65100"];
veille -> bdd [label="met à jour\nles sources", color="#E65100", style=dashed];
// Sources → BDD (alimentation)
sources -> bdd [label="alimente\nles données", color="#546E7A", style=dashed];
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 KiB

View File

@ -1,147 +0,0 @@
digraph macro_dat {
rankdir=TB;
fontname="Arial";
node [fontname="Arial", fontsize=10, style=filled, shape=record];
edge [fontname="Arial", fontsize=9];
label="FabNum — Macro-DAT (Diagramme d'Activités Technique)\n\n";
labelloc=t;
fontsize=16;
compound=true;
// ==================== COUCHE STOCKAGE ====================
subgraph cluster_stockage {
label="COUCHE STOCKAGE";
style=filled; color="#E3F2FD"; fontsize=13; fontcolor="#1565C0";
base_graphe [label="Base graphe\n(Neo4j / PG+AGE / ArangoDB)|• Nœuds (tous niveaux)\n• Arêtes + attributs\n• Multi-graphes\n• Schéma évolutif\n• Open source", fillcolor="#BBDEFB"];
historisation [label="Historisation|• Snapshots horodatés\n• Versions données\n• Versions indices\n• Audit trail", fillcolor="#BBDEFB"];
sources_db [label="Référentiel sources|• Sources catégorisées\n• Tiers de confiance\n (par domaine)\n• Liens source↔donnée", fillcolor="#BBDEFB"];
}
// ==================== COUCHE MOTEUR ====================
subgraph cluster_moteur {
label="COUCHE MOTEUR (Python)";
style=filled; color="#E8F5E9"; fontsize=13; fontcolor="#2E7D32";
subgraph cluster_calcul {
label="Calcul";
style=filled; color="#C8E6C9";
calcul_indices [label="Calcul indices|IHH, ICS, IVC, ISG\n+ futurs (eau, énergie)\nPré-calcul à chaque MAJ", fillcolor="#A5D6A7"];
meta_indices [label="Méta-indices|Calcul dynamique\nsur sous-graphe\nsélectionné", fillcolor="#A5D6A7"];
}
subgraph cluster_qualite {
label="Qualité données";
style=filled; color="#C8E6C9";
arbitrage [label="Arbitrage sources|Tier 1 par défaut\nConvergence → alerte\nSeuils variation", fillcolor="#A5D6A7"];
qualification [label="Qualification|Filtres qualité\nIndice fiabilité\nPérimètre mesuré", fillcolor="#A5D6A7"];
}
subgraph cluster_requetage {
label="Requêtage";
style=filled; color="#C8E6C9";
chemins [label="Traversée graphe|Chemins critiques\nFiltrage multi-critères\nSous-graphes", fillcolor="#A5D6A7"];
projection [label="Projection SI|Mapping SI client\nsur graphe FabNum\n(stateless)", fillcolor="#A5D6A7"];
}
subgraph cluster_generation {
label="Génération";
style=filled; color="#C8E6C9";
templates [label="Templates fiches|Niveau × usage\nExpertise / Synthèse\nAPI / JSON", fillcolor="#A5D6A7"];
import_export [label="Import / Export|DOT (legacy)\nJSON\nPDF\nBackup / Restore", fillcolor="#A5D6A7"];
}
}
// ==================== SERVICES INTERNES ====================
subgraph cluster_services_internes {
label="SERVICES INTERNES (non exposés)";
style=filled; color="#FFF3E0"; fontsize=13; fontcolor="#E65100";
veille [label="Veille sources\n(huginn)|Détection MAJ\nNouvelles sources\nDisparitions", fillcolor="#FFE0B2"];
verif_citations [label="Vérification\ncitations|verify-citations\n(à faire évoluer)", fillcolor="#FFE0B2"];
recalcul [label="Recalcul\nindices|Déclenché par\nMAJ graphe\n(mensuel → trim.)", fillcolor="#FFE0B2"];
alertes [label="Alertes|Variations anormales\nConvergence sources\nÉvénements climat.", fillcolor="#FFE0B2"];
}
// ==================== API REST ====================
subgraph cluster_api {
label="API REST (point d'accès unique)";
style=filled; color="#F3E5F5"; fontsize=13; fontcolor="#6A1B9A";
subgraph cluster_securite {
label="Sécurité";
style=filled; color="#E1BEE7";
auth [label="Authentification|User / API key\nRôles (admin/expert/service)", fillcolor="#CE93D8"];
profils [label="Profils visibilité|Chaîne principale / +connexes\nIndices complets / partiels\nPrédéfinis / sur mesure", fillcolor="#CE93D8"];
rate_limit [label="Rate limiting\n+ Monitoring|Logging structuré\nMétriques\nAlerting", fillcolor="#CE93D8"];
}
subgraph cluster_endpoints {
label="Endpoints";
style=filled; color="#E1BEE7";
ep_graphe [label="/graphe/*|Requêtage\n(expert / simplifié)", fillcolor="#CE93D8"];
ep_fiches [label="/fiches/*|Consultation\n(tous formats)", fillcolor="#CE93D8"];
ep_analyse [label="/analyse/*|Vulnérabilités\nScénarios", fillcolor="#CE93D8"];
ep_indices [label="/indices/*|Méta-indices\ndynamiques", fillcolor="#CE93D8"];
ep_export [label="/export/*|PDF, JSON, DOT", fillcolor="#CE93D8"];
ep_admin [label="/admin/*|CRUD graphe\nGestion sources\nTiers, arbitrage", fillcolor="#CE93D8"];
}
}
// ==================== CONSOMMATEURS ====================
subgraph cluster_consommateurs {
label="CONSOMMATEURS";
style=filled; color="#ECEFF1"; fontsize=13; fontcolor="#37474F";
frontend [label="Frontend expert|COMEX : synthèses\nMétiers : analyse opérat.\nDSAI : dépendances SI", fillcolor="#CFD8DC", shape=house];
services_ext [label="Services externes|Génération IA rapports\nAgent local client\nExport manuel", fillcolor="#CFD8DC", shape=house];
ecosysteme [label="Écosystème 360°|Veille stratégique\nIRON\nAlertes croisées", fillcolor="#CFD8DC", shape=house];
}
// Admin
admin [label="Admin (scripts)|CRUD graphe\nGestion sources\nTiers, arbitrage\nBackup / restore", fillcolor="#FFCC80", shape=hexagon];
// ==================== LIENS ====================
// Stockage → Moteur
base_graphe -> chemins [color="#1565C0"];
base_graphe -> calcul_indices [color="#1565C0"];
historisation -> meta_indices [style=dashed, color="#1565C0"];
sources_db -> arbitrage [color="#1565C0"];
sources_db -> qualification [color="#1565C0"];
// Moteur → Services internes
calcul_indices -> recalcul [color="#E65100"];
arbitrage -> alertes [color="#E65100"];
qualification -> verif_citations [color="#E65100", style=dashed];
// Moteur → API
chemins -> ep_graphe [color="#6A1B9A"];
meta_indices -> ep_indices [color="#6A1B9A"];
templates -> ep_fiches [color="#6A1B9A"];
import_export -> ep_export [color="#6A1B9A"];
projection -> ep_graphe [color="#6A1B9A", style=dashed];
calcul_indices -> ep_analyse [color="#6A1B9A"];
// Sécurité → Endpoints
auth -> ep_graphe [style=dotted, color="#6A1B9A"];
profils -> ep_graphe [style=dotted, color="#6A1B9A"];
// API → Consommateurs
ep_graphe -> frontend [color="#37474F", penwidth=1.5];
ep_fiches -> frontend [color="#37474F", penwidth=1.5];
ep_analyse -> frontend [color="#37474F", penwidth=1.5];
ep_export -> services_ext [color="#37474F", penwidth=1.5];
ep_graphe -> ecosysteme [color="#37474F", penwidth=1.5];
ep_indices -> ecosysteme [color="#37474F", penwidth=1.5];
ep_graphe -> services_ext [color="#37474F", penwidth=1.5];
// Admin
admin -> ep_admin [color="#E65100", penwidth=2];
admin -> base_graphe [color="#E65100", penwidth=2, label="accès\ndirect"];
// Services internes → Stockage (boucle)
veille -> sources_db [color="#E65100", style=dashed, label="MAJ\nsources"];
recalcul -> base_graphe [color="#E65100", style=dashed, label="MAJ\nindices"];
alertes -> admin [color="#E65100", style=dashed, label="notification"];
}