appflows 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. appflows-1.0.0/.gitignore +21 -0
  2. appflows-1.0.0/CHANGELOG.md +560 -0
  3. appflows-1.0.0/LICENSE +21 -0
  4. appflows-1.0.0/PKG-INFO +211 -0
  5. appflows-1.0.0/README.md +178 -0
  6. appflows-1.0.0/docker/README.md +173 -0
  7. appflows-1.0.0/docs/algorithme.md +714 -0
  8. appflows-1.0.0/docs/api.md +1069 -0
  9. appflows-1.0.0/docs/cli.md +57 -0
  10. appflows-1.0.0/docs/developpement.md +75 -0
  11. appflows-1.0.0/docs/formats.md +985 -0
  12. appflows-1.0.0/docs/images/api/01-minimal.png +0 -0
  13. appflows-1.0.0/docs/images/api/01-minimal.svg +35 -0
  14. appflows-1.0.0/docs/images/api/02-depuis-un-fichier.png +0 -0
  15. appflows-1.0.0/docs/images/api/02-depuis-un-fichier.svg +37 -0
  16. appflows-1.0.0/docs/images/api/03-choisir-le-cote.png +0 -0
  17. appflows-1.0.0/docs/images/api/03-choisir-le-cote.svg +42 -0
  18. appflows-1.0.0/docs/images/api/04-bus.png +0 -0
  19. appflows-1.0.0/docs/images/api/04-bus.svg +56 -0
  20. appflows-1.0.0/docs/images/api/05-layout-explicite.png +0 -0
  21. appflows-1.0.0/docs/images/api/05-layout-explicite.svg +54 -0
  22. appflows-1.0.0/docs/images/api/06-lecture-fonctionnelle.png +0 -0
  23. appflows-1.0.0/docs/images/api/06-lecture-fonctionnelle.svg +42 -0
  24. appflows-1.0.0/docs/images/api/06-lecture-technique.png +0 -0
  25. appflows-1.0.0/docs/images/api/06-lecture-technique.svg +50 -0
  26. appflows-1.0.0/docs/images/api/07-tags.png +0 -0
  27. appflows-1.0.0/docs/images/api/07-tags.svg +45 -0
  28. appflows-1.0.0/docs/images/api/08-habillage.png +0 -0
  29. appflows-1.0.0/docs/images/api/08-habillage.svg +32 -0
  30. appflows-1.0.0/docs/images/api/09-export.png +0 -0
  31. appflows-1.0.0/docs/images/api/09-export.svg +32 -0
  32. appflows-1.0.0/docs/images/api/10-perimetre-achats.png +0 -0
  33. appflows-1.0.0/docs/images/api/10-perimetre-achats.svg +32 -0
  34. appflows-1.0.0/docs/images/api/10-perimetre-rh.png +0 -0
  35. appflows-1.0.0/docs/images/api/10-perimetre-rh.svg +32 -0
  36. appflows-1.0.0/docs/images/api/11-objets-minimal.png +0 -0
  37. appflows-1.0.0/docs/images/api/11-objets-minimal.svg +35 -0
  38. appflows-1.0.0/docs/images/api/12-objets-bus.png +0 -0
  39. appflows-1.0.0/docs/images/api/12-objets-bus.svg +56 -0
  40. appflows-1.0.0/docs/images/api/13-objets-fonctionnel.png +0 -0
  41. appflows-1.0.0/docs/images/api/13-objets-fonctionnel.svg +42 -0
  42. appflows-1.0.0/docs/images/api/13-objets-technique.png +0 -0
  43. appflows-1.0.0/docs/images/api/13-objets-technique.svg +50 -0
  44. appflows-1.0.0/docs/images/api/14-objets-tags.png +0 -0
  45. appflows-1.0.0/docs/images/api/14-objets-tags.svg +53 -0
  46. appflows-1.0.0/docs/images/api/15-objets-depuis-donnees.png +0 -0
  47. appflows-1.0.0/docs/images/api/15-objets-depuis-donnees.svg +51 -0
  48. appflows-1.0.0/docs/images/api/16-doctype.png +0 -0
  49. appflows-1.0.0/docs/images/api/16-doctype.svg +71 -0
  50. appflows-1.0.0/docs/images/finances.png +0 -0
  51. appflows-1.0.0/docs/images/finances.svg +123 -0
  52. appflows-1.0.0/docs/images/patient-appli.png +0 -0
  53. appflows-1.0.0/docs/images/patient-appli.svg +56 -0
  54. appflows-1.0.0/docs/images/patient-tech.png +0 -0
  55. appflows-1.0.0/docs/images/patient-tech.svg +70 -0
  56. appflows-1.0.0/docs/images/resultats.png +0 -0
  57. appflows-1.0.0/docs/images/resultats.svg +98 -0
  58. appflows-1.0.0/docs/images/soins.png +0 -0
  59. appflows-1.0.0/docs/images/soins.svg +153 -0
  60. appflows-1.0.0/docs/publication.md +132 -0
  61. appflows-1.0.0/docs/ui.md +81 -0
  62. appflows-1.0.0/examples/01_minimal.py +33 -0
  63. appflows-1.0.0/examples/02_depuis_un_fichier.py +40 -0
  64. appflows-1.0.0/examples/03_choisir_le_cote.py +33 -0
  65. appflows-1.0.0/examples/04_bus.py +34 -0
  66. appflows-1.0.0/examples/05_layout_explicite.py +32 -0
  67. appflows-1.0.0/examples/06_schema_technique.py +36 -0
  68. appflows-1.0.0/examples/07_tags.py +41 -0
  69. appflows-1.0.0/examples/08_habillage.py +60 -0
  70. appflows-1.0.0/examples/09_export_png.py +30 -0
  71. appflows-1.0.0/examples/10_traitement_par_lot.py +61 -0
  72. appflows-1.0.0/examples/11_objets_minimal.py +36 -0
  73. appflows-1.0.0/examples/12_objets_bus.py +36 -0
  74. appflows-1.0.0/examples/13_objets_connecteurs.py +40 -0
  75. appflows-1.0.0/examples/14_objets_tags.py +42 -0
  76. appflows-1.0.0/examples/15_objets_depuis_donnees.py +83 -0
  77. appflows-1.0.0/examples/16_doctype.py +44 -0
  78. appflows-1.0.0/examples/README.md +53 -0
  79. appflows-1.0.0/examples/build.py +124 -0
  80. appflows-1.0.0/examples/yaml/bus.yaml +25 -0
  81. appflows-1.0.0/examples/yaml/config.yaml +83 -0
  82. appflows-1.0.0/examples/yaml/explicite.yaml +25 -0
  83. appflows-1.0.0/examples/yaml/finances.yaml +41 -0
  84. appflows-1.0.0/examples/yaml/minimal.yaml +14 -0
  85. appflows-1.0.0/examples/yaml/patient.yaml +22 -0
  86. appflows-1.0.0/examples/yaml/resultats.yaml +27 -0
  87. appflows-1.0.0/examples/yaml/socle.yaml +15 -0
  88. appflows-1.0.0/examples/yaml/soins.yaml +39 -0
  89. appflows-1.0.0/examples/yaml/technique.yaml +26 -0
  90. appflows-1.0.0/pyproject.toml +130 -0
  91. appflows-1.0.0/src/appflows/__init__.py +94 -0
  92. appflows-1.0.0/src/appflows/cli.py +237 -0
  93. appflows-1.0.0/src/appflows/config.py +533 -0
  94. appflows-1.0.0/src/appflows/formats.py +574 -0
  95. appflows-1.0.0/src/appflows/generator.py +934 -0
  96. appflows-1.0.0/src/appflows/layout.py +845 -0
  97. appflows-1.0.0/src/appflows/logtext.py +24 -0
  98. appflows-1.0.0/src/appflows/models.py +307 -0
  99. appflows-1.0.0/src/appflows/py.typed +0 -0
  100. appflows-1.0.0/src/appflows/rows.py +207 -0
  101. appflows-1.0.0/src/appflows/sides.py +189 -0
  102. appflows-1.0.0/src/appflows/svg.py +494 -0
  103. appflows-1.0.0/src/appflows/ui/__init__.py +10 -0
  104. appflows-1.0.0/src/appflows/ui/app.py +346 -0
  105. appflows-1.0.0/src/appflows/ui/server.py +101 -0
  106. appflows-1.0.0/src/appflows/ui/service.py +226 -0
  107. appflows-1.0.0/src/appflows/ui/static/editor.js +646 -0
  108. appflows-1.0.0/src/appflows/ui/static/index.html +82 -0
  109. appflows-1.0.0/src/appflows/ui/static/style.css +333 -0
  110. appflows-1.0.0/tests/conftest.py +49 -0
  111. appflows-1.0.0/tests/data/appli_backward_syntax.yaml +17 -0
  112. appflows-1.0.0/tests/data/appli_bus_cascade.yaml +15 -0
  113. appflows-1.0.0/tests/data/appli_direct_link_grouping.yaml +15 -0
  114. appflows-1.0.0/tests/data/appli_flow_with_url.yaml +12 -0
  115. appflows-1.0.0/tests/data/appli_label_escaped_comma.yaml +11 -0
  116. appflows-1.0.0/tests/data/appli_layout_auto_bus_balance.yaml +30 -0
  117. appflows-1.0.0/tests/data/appli_layout_explicit_dual_side.yaml +20 -0
  118. appflows-1.0.0/tests/data/appli_minimal.yaml +13 -0
  119. appflows-1.0.0/tests/data/appli_multi_label_deficit.yaml +16 -0
  120. appflows-1.0.0/tests/data/appli_multi_label_exact.yaml +14 -0
  121. appflows-1.0.0/tests/data/appli_multi_label_excess.yaml +13 -0
  122. appflows-1.0.0/tests/data/appli_stacked_flows.yaml +14 -0
  123. appflows-1.0.0/tests/data/appli_tags.yaml +17 -0
  124. appflows-1.0.0/tests/data/appli_tech_connectors_both_ends.yaml +16 -0
  125. appflows-1.0.0/tests/data/appli_tech_mixed_directions.yaml +23 -0
  126. appflows-1.0.0/tests/data/appli_tech_no_bus_fallback.yaml +15 -0
  127. appflows-1.0.0/tests/data/appli_tech_protocol_only.yaml +17 -0
  128. appflows-1.0.0/tests/data/config-custom.yaml +17 -0
  129. appflows-1.0.0/tests/data/config.yaml +79 -0
  130. appflows-1.0.0/tests/data/dense.yaml +17 -0
  131. appflows-1.0.0/tests/data/doctype_basic.yaml +16 -0
  132. appflows-1.0.0/tests/data/doctype_default_label_fallback.yaml +13 -0
  133. appflows-1.0.0/tests/data/doctype_dual_role_and_block_seam.yaml +20 -0
  134. appflows-1.0.0/tests/data/doctype_tech_connectors.yaml +16 -0
  135. appflows-1.0.0/tests/data/doctype_tech_mixed_directions.yaml +16 -0
  136. appflows-1.0.0/tests/data/stocks.yaml +15 -0
  137. appflows-1.0.0/tests/data/traversee.yaml +14 -0
  138. appflows-1.0.0/tests/js/coloration.test.js +220 -0
  139. appflows-1.0.0/tests/js/editeur.test.js +613 -0
  140. appflows-1.0.0/tests/js/faux-dom.js +278 -0
  141. appflows-1.0.0/tests/js/harnais.js +160 -0
  142. appflows-1.0.0/tests/js/indentation.test.js +226 -0
  143. appflows-1.0.0/tests/js/page.test.js +63 -0
  144. appflows-1.0.0/tests/test_cli.py +167 -0
  145. appflows-1.0.0/tests/test_config.py +326 -0
  146. appflows-1.0.0/tests/test_e2e.py +291 -0
  147. appflows-1.0.0/tests/test_editor_js.py +30 -0
  148. appflows-1.0.0/tests/test_formats.py +586 -0
  149. appflows-1.0.0/tests/test_generator.py +2382 -0
  150. appflows-1.0.0/tests/test_generator_errors.py +500 -0
  151. appflows-1.0.0/tests/test_logtext.py +43 -0
  152. appflows-1.0.0/tests/test_samples.py +91 -0
  153. appflows-1.0.0/tests/test_ui.py +765 -0
@@ -0,0 +1,21 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+
5
+ # build / packaging
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+
10
+ # outils
11
+ .pytest_cache/
12
+ .ruff_cache/
13
+ .coverage
14
+ .claude/
15
+ htmlcov/
16
+
17
+ # artefacts d'exécution
18
+ errors.log
19
+
20
+ # analyses locales
21
+ docs/analyses/
@@ -0,0 +1,560 @@
1
+ # Journal des modifications
2
+
3
+ Le format suit [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/) et le
4
+ versionnage [SemVer](https://semver.org/lang/fr/).
5
+
6
+ ## [1.0.0] — 2026-10-10
7
+
8
+ ### Modifié
9
+
10
+ - Le projet s'appelle désormais **appflows** (anciennement `schema-archi`) :
11
+ distribution PyPI `appflows`, paquet `import appflows`, commandes
12
+ `appflows` et `appflows-ui`, images conteneur `appflows` et
13
+ `appflows-bulk`, dépôt `framagit.org/opikanoba/appflows`. Aucun alias
14
+ `schema_archi` n'est fourni ; `schema-archi` reste figé en 0.12.1 sur PyPI.
15
+ - Variables d'environnement de l'éditeur web préfixées `APPFLOWS_`.
16
+
17
+ ### Déprécié
18
+
19
+ - Les variables `SCHEMA_ARCHI_*` sont encore lues, avec un avertissement au
20
+ journal, quand leur équivalent `APPFLOWS_*` est absent.
21
+
22
+ ## [0.12.1] — 2026-09-26
23
+
24
+ ### Ajouté
25
+
26
+ - Chaînes de flux à **sens mêlés** : `m <-(sftp:22)- eie -(mllp:2575)-> pacs`
27
+ décrit un seul flux de `m` vers `pacs`, où le bus va chercher puis pousse.
28
+ La donnée se lit de gauche à droite ; la flèche dit qui initie la connexion,
29
+ et son connecteur passe sur le nœud visé. Placement inchangé.
30
+ - `Link(reverse=True)`, équivalent objet d'un lien écrit `<-` dans une telle
31
+ chaîne.
32
+
33
+ ### Modifié
34
+
35
+ - Un bus dont seule la sortie porte un connecteur reçoit une entrée neutre,
36
+ comme il recevait déjà une sortie neutre face à une entrée déclarée.
37
+ - La ligne `a --> e1 <-- m` n'est plus refusée pour « sens contradictoires » :
38
+ elle se lit comme un flux de `a` vers `m`.
39
+
40
+ ## [0.12.0] — 2026-09-22
41
+
42
+ ### Ajouté
43
+
44
+ - Une seconde topologie, `type: doctype`, qui suit un **type de document**
45
+ plutôt qu'une application : ceux qui le produisent à gauche, ceux qui le
46
+ consomment à droite, les bus entre les deux, et pas d'application centrale.
47
+ - `examples/yaml/resultats.yaml` et `examples/16_doctype.py` illustrent la
48
+ nouvelle topologie ; modification du README et `docs/api.md`.
49
+ - 20 définitions dans `tests/data/` couvrant les combinaisons de topologie,
50
+ disposition et grammaire de flux (bus en cascade, libellés multiples,
51
+ tags, connecteurs, etc.), destinées aux futurs tests de non-régression.
52
+ - `docs/analyses/` : rapport d'analyse de code avant publication — aucun
53
+ défaut bloquant.
54
+
55
+ ### Modifié
56
+
57
+ - `docs/formats.md` est réorganisé
58
+ - Revue du README
59
+
60
+ ## [0.11.0] — 2026-09-20
61
+
62
+ ### Ajouté
63
+
64
+ - `scripts/build_container.sh` construit les images conteneur (éditeur web,
65
+ lot, ou les deux), taguées de la version du projet, et **vérifie** chacune
66
+ sans privilège — `--read-only`, `--cap-drop ALL`, `no-new-privileges`
67
+ - `scripts/run_container.sh` lance l'éditeur en conteneur confiné, sans
68
+ limite de taille par défaut (`--max-flows`, `--max-apps` pour en poser),
69
+ au premier plan ou en arrière-plan (`--detach`, `--stop`), avec `--dry-run`.
70
+ - `scripts/check.sh`, la barrière qualité en une commande — ruff, pyright,
71
+ pytest, et `--matrix` pour rejouer pytest sur Python 3.11 à 3.14 via uv.
72
+ `build-release.sh` l'appelle, et un crochet `pre-push` versionné
73
+ (`git config core.hooksPath scripts/hooks`) la lance avant tout envoi.
74
+ - Un `flow.margin` trop petit pour la hauteur des pastilles de connecteur est
75
+ signalé au chargement de la configuration
76
+ - Une virgule s'écrit dans un libellé en l'échappant : `[commande\, urgente]`
77
+ est un seul libellé, dessiné `commande, urgente`.
78
+ - Les extras `png` et `ui` rejoignent le groupe `dev` : `uv run pytest`
79
+ exerce désormais l'export PNG et l'API web au lieu de sauter leurs tests.
80
+ - `tests/test_e2e.py` : l'éditeur web joué dans un vrai Chromium
81
+ - Éditeur web : chaque panneau est plafonné à 200 000 caractères et un corps
82
+ de requête annoncé trop gros est refusé avant lecture (`413`), pour qu'une
83
+ saisie démesurée ne mobilise pas le serveur.
84
+ - `examples/finances.yaml` et `examples/soins.yaml`, définitions des deux
85
+ illustrations du README, désormais régénérées par `sample/build.py` avec
86
+ les images de la documentation.
87
+ - L'exemple « Format de définition » du README est `examples/yaml/patient.yaml`
88
+ — un bus, MLLP et SFTP —, rendu par `examples/build.py` dans ses deux
89
+ lectures (`patient-appli.png`, `patient-tech.png`) pour montrer d'un coup
90
+ d'œil ce que la clé `type` change.
91
+ - Éditeur web : le séparateur entre les panneaux se glisse à la souris pour
92
+ élargir la saisie ou l'aperçu, se déplace au clavier (flèches, Début, Fin)
93
+ et revient au partage initial sur double-clic. Le partage est retenu par le
94
+ navigateur.
95
+ - API objet : `Generator` accepte des `Application` et `Bus` à la place des
96
+ dictionnaires code → libellé, et un `Link(source, target, protocol, port)` —
97
+ ou une liste de liens qui s'enchaînent — à la place de la chaîne d'un flux.
98
+ Le rôle de l'application centrale fixe la colonne (source → droite, cible →
99
+ gauche). Cinq exemples, `sample/11` à `15`, reprennent les définitions texte.
100
+ - Un libellé par flèche sur une chaîne relayée : `a --> bus --> m [DOC1, DOC2]`
101
+ écrit `DOC1` au-dessus de la première flèche et `DOC2` au-dessus de la
102
+ seconde.
103
+ - Dix exemples commentés d'utilisation de l'API Python dans `sample/`
104
+ - Clé de définition `layout`, `auto` (défaut) ou `explicit`. En `explicit`, le
105
+ sens d'écriture décide seul du côté de chaque boîte, **bus compris** : `a -->
106
+ esb --> m` place `a` et `esb` à gauche, `m --> esb --> b` les place à droite.
107
+ C'est la seule façon de choisir le côté d'un bus, et un même bus écrit des
108
+ deux côtés ouvre désormais une boîte de chaque côté.
109
+ - Exemple `examples/explicite.yaml`, qui montre une application et un bus
110
+ dessinés de part et d'autre du centre.
111
+
112
+ ### Modifié
113
+
114
+ - Un seul répertoire d'exemples : `sample/` disparaît, ses quinze programmes
115
+ Python, `build.py` et leur README rejoignent `examples/`, dont les
116
+ définitions YAML et `config.yaml` passent dans `examples/yaml/`. Les rendus
117
+ de la documentation suivent, de `docs/images/sample/` vers
118
+ `docs/images/api/`.
119
+
120
+ - Les fonctions et méthodes des tests (Python et JavaScript), de l'éditeur
121
+ web et des scripts portent des noms anglais, comme le reste du code ; le
122
+ module `journal.py` devient `logtext.py`.
123
+
124
+ - Les exemples, jeux de test et extraits de documentation emploient des noms
125
+ d'application génériques (« Gestion financière », « Dossier de soins »,
126
+ « Messagerie »…) à la place de noms de produits réels ;
127
+ `examples/magh2.yaml`, `cora.yaml` et `opik.yaml` deviennent
128
+ `finances.yaml`, `soins.yaml` et `socle.yaml`.
129
+
130
+ - `graph()` calcule la géométrie lui-même quand `calculate_positions()` n'a
131
+ pas été appelé : instancier `Generator` puis appeler `graph()` suffit.
132
+ L'appel explicite reste possible, pour lire les coordonnées avant de
133
+ dessiner. Remplacer `graph_config` ou relire les flux fait recalculer au
134
+ prochain `graph()`.
135
+
136
+ - **Configuration hiérarchisée.** `GraphConfig` est découpée par sujet —
137
+ `page`, `app`, `main`, `flow`, `tag`, `bus`, `connector` —, chaque sujet
138
+ étant une dataclass (`AppConfig`, `FlowConfig`…) et chaque paire un objet
139
+ (`padding.x`, `label.halo.width`).
140
+
141
+ - **La virgule sépare désormais les libellés d'un flux** : un libellé ne peut
142
+ plus en contenir. `[commande, urgente]` se lit comme deux libellés au lieu
143
+ d'un seul.
144
+
145
+ - La boîte d'un bus s'ouvre désormais à la hauteur de l'application centrale, et
146
+ se ferme avec elle quand aucun lien direct ne s'affiche sous ses traversées :
147
+ un côté entièrement relayé donne une boîte exactement aussi haute que le
148
+ centre. Elle cède devant ce qui occupe déjà sa colonne — un second bus, la
149
+ flèche d'un flux qui la traverse. Sa largeur, elle, ne change pas.
150
+
151
+ - **Changement de comportement par défaut** : en `layout: auto`, les liens
152
+ directs d'une même application sont désormais regroupés d'un seul côté — une
153
+ seule boîte, plus haute — là où deux écritures opposées (`p --> m` et `m -->
154
+ p`) donnaient jusqu'ici deux boîtes homonymes. Le côté retenu est celui de ses
155
+ flux relayés s'il y en a, sinon celui que désignent le plus de ses lignes ; à
156
+ égalité, la première déclarée. Pour retrouver les deux boîtes, déclarer
157
+ `layout: explicit`.
158
+
159
+ - Le choix du côté quitte `generator.py` pour un module dédié, `sides.py`.
160
+ `Generator.parse_flows` retombe du rang C 16 au rang C 11.
161
+
162
+ - Le protocole d'un connecteur s'écrit en graisse normale, comme le port qui
163
+ l'accompagne, et non plus en gras.
164
+
165
+ ### Supprimé
166
+
167
+ - La forme plate `parameters:` (`APP_FONT_SIZE`, `TAG_COLORS: [...]`) n'est
168
+ plus lue, sans compatibilité : un fichier qui la contient est refusé avec un
169
+ message explicite. Une table de conversion figure dans `docs/formats.md` § 4.
170
+
171
+ ### Corrigé
172
+
173
+ - **Sécurité, éditeur web.** Deux entrées de moins de deux kilo-octets
174
+ occupaient le serveur huit à dix secondes et jusqu'à plusieurs centaines de
175
+ mégaoctets : une bombe d'alias YAML, et un document de mille crochets
176
+ ouvrants (récursion du parseur). Le YAML est désormais lu par un chargeur
177
+ strict — sans alias, borné à 32 niveaux —, la forme de la définition est
178
+ contrôlée avant usage (libellés, lignes de flux, `main`/`type`/`layout`),
179
+ et un corps sans `Content-Length` est refusé en 411 avant lecture. L'export
180
+ PNG refuse en 400 un raster au-delà de 25 mégapixels et les erreurs Cairo
181
+ (qui sortaient en 500) ; les rendus passent par un exécuteur borné sous
182
+ délai (`503` au-delà), et uvicorn limite ses connexions, coupe les
183
+ connexions oisives et n'annonce plus sa version — le tout réglable par
184
+ `SCHEMA_ARCHI_RENDER_WORKERS`, `SCHEMA_ARCHI_RENDER_TIMEOUT` et
185
+ `SCHEMA_ARCHI_CONCURRENCY`. Un schéma de plus de 200 flux ou de 100
186
+ applications et bus est refusé en 400 avant toute analyse
187
+ (`SCHEMA_ARCHI_MAX_FLOWS`, `SCHEMA_ARCHI_MAX_APPS`, `0` pour lever la
188
+ limite) ; la page l'annonce dans un bandeau, avec le rappel qu'une
189
+ installation locale n'a pas cette contrainte ; la bibliothèque et la
190
+ commande restent sans limite. Une réponse 422 ne recopie plus le document
191
+ reçu, et un lien `//autre-site/` n'est plus rendu cliquable. Toute réponse
192
+ porte une politique de sécurité de contenu (`script-src 'self'`) et les
193
+ en-têtes `nosniff`, `X-Frame-Options`, `Referrer-Policy` ; un limiteur de
194
+ débit par adresse (`SCHEMA_ARCHI_RATE_LIMIT`, 5 rendus/s, rafale 20)
195
+ répond 429 aux clients qui enchaînent les rendus ; `X-Forwarded-For` n'est
196
+ lu que sur demande (`SCHEMA_ARCHI_PROXY_HEADERS`). `docker/README.md`
197
+ décrit l'exposition publique : conteneur confiné, Caddy ou nginx. Le
198
+ journal cite l'adresse d'origine des saisies refusées et n'en reprend
199
+ qu'un extrait borné sur une ligne (`logtext.excerpt`) ; les liens du SVG
200
+ s'ouvrent dans un nouvel onglet, sans `opener` ni `Referer`. Analyse
201
+ complète dans `docs/analyses/analyse-2026-09-19-securite-web.md`.
202
+ - Éditeur web : `Tab` et `Maj+Tab` passent par `insertText` au lieu de
203
+ réécrire le champ, si bien que `Ctrl+Z` annule l'indentation et remonte
204
+ toujours aux frappes d'avant. Sans `insertText`, l'écriture directe reste le
205
+ repli.
206
+ - Deux bus empilés dans une même colonne se fermaient chacun sur leur
207
+ contenu, séparés d'un double blanc ; ils avancent désormais l'un vers l'autre
208
+ jusqu'à `page.vspace`. Les bus d'une même chaîne s'ouvrent et se ferment à
209
+ la même hauteur. Devant un lien direct, une boîte de bus continue de se
210
+ fermer sur son contenu : c'est voulu.
211
+ - Le libellé d'un lien direct placé du même côté qu'un bus pouvait déborder
212
+ sur les boîtes des deux bouts : sa flèche traverse deux bandes et la colonne
213
+ du bus, et rien ne vérifiait que l'ensemble lui suffisait. Le manque est
214
+ désormais réparti sur les bandes traversées ; les schémas où le libellé
215
+ tenait déjà ne changent pas.
216
+ - Nom d'application, nom de bus, libellé de flux et port posent leur ligne de
217
+ base eux-mêmes, comme les pastilles, au lieu de `dominant-baseline="middle"`
218
+ : ils tombaient 1 à 2 px trop haut, et pas au même endroit dans un
219
+ navigateur et dans le PNG de cairosvg. Le SVG ne contient plus aucun
220
+ `dominant-baseline`.
221
+ - Éditeur web : le glissement du séparateur mesurait depuis le bord du
222
+ conteneur et non du panneau, d'où un décalage d'une marge intérieure entre
223
+ le pointeur et la gouttière. Trouvé par le test de bout en bout.
224
+ - Éditeur web : la coloration n'est plus refaite en entier à chaque touche.
225
+ Elle est calculée ligne par ligne avec mémoire — une frappe ne recolore que
226
+ sa ligne — et regroupée par image d'écran (`requestAnimationFrame`), de
227
+ sorte que la saisie ne l'attend jamais.
228
+ - Les illustrations du README (`docs/images/finances.png` et `soins.png`,
229
+ autrefois `magh2.png` et `cora.png`) dataient d'avant la
230
+ 0.9.0 et n'avaient pas de définition source dans le dépôt.
231
+ - pyright est déclaré dans le groupe `dev` et verrouillé par `uv.lock` :
232
+ `build-release.sh` ne l'installe plus à la volée dans une version flottante.
233
+ - Le tag d'un bus (`esb: EAI !interne`, ou `Bus(..., tag="interne")`) était
234
+ accepté mais jamais dessiné. Il l'est désormais, en pastille sous le nom,
235
+ dans une bande de titre ouverte d'autant ; la boîte s'élargit à un tag plus
236
+ large que le nom, et les couleurs se dérivent de celles du bus faute d'être
237
+ déclarées dans `tag.colors`.
238
+ - La documentation citait un paramètre `CONNECTOR_DEFAULT_COLORS` qui n'a
239
+ jamais existé : les couleurs d'un connecteur non déclaré sont dérivées de
240
+ sa boîte.
241
+ - La pastille d'un connecteur n'entrait dans la largeur d'aucune boîte : au-delà
242
+ d'une douzaine de caractères, un protocole recouvrait la boîte entière,
243
+ ressortait du bord opposé et son port s'écrivait hors du cadre. Une boîte
244
+ réserve désormais la place que ses pastilles réclament à l'intérieur.
245
+ - La boîte d'un bus mordait sur le groupe suivant dès que `CONNECTOR_LABEL_GAP`
246
+ dépassait ce que `VSPACE` absorbait (77 aux autres valeurs par défaut) : la
247
+ mise en page réservait le blanc au-dessus d'un groupe de bus, jamais celui du
248
+ dessous. Une flèche voisine traversait alors la boîte.
249
+ - Les paramètres de `parameters` n'étaient contrôlés qu'en type : un `VSPACE`
250
+ négatif, un `APP_PARAM` nul ou une taille de police nulle étaient retenus en
251
+ silence et produisaient un schéma illisible. Ils sont désormais bornés, et une
252
+ valeur hors intervalle est signalée puis remplacée par le défaut.
253
+ - Un flux traversant **deux bus ou plus et écrit l'application centrale en
254
+ dernier** (`a --> e1 --> e2 --> m`) annonçait sa chaîne dans l'ordre
255
+ d'écriture, à rebours de l'ordre de placement. Deux emplacements pourtant
256
+ identiques passaient pour distincts : la colonne était mal triée, les boîtes
257
+ de bus s'étiraient sur toute sa hauteur, et la flèche d'un flux qui
258
+ n'empruntait pas un bus traversait sa boîte de part en part — donnant à lire
259
+ un raccordement inexistant. La chaîne d'un emplacement est désormais posée par
260
+ la répartition, dans l'ordre vu depuis le centre.
261
+ - Le protocole d'un connecteur et le texte d'un tag remontaient au-dessus du
262
+ centre de leur pastille : `dominant-baseline="middle"` aligne sur la
263
+ demi-hauteur d'x, non sur celle des capitales. Ces deux libellés posent
264
+ désormais leur ligne de base eux-mêmes, ce qui aligne du même coup le SVG et
265
+ le PNG, que cairosvg centrait autrement.
266
+ - Éditeur web : une définition bien formée en YAML mais mal structurée — un
267
+ `main:` qui désigne une application inconnue, un `apps:` donné en liste, un
268
+ flux non textuel — sortait en `500 Internal Server Error`, et l'éditeur
269
+ n'affichait plus que « Échec de la requête (500) ». Ces saisies sont
270
+ désormais converties en `400` avec le message d'origine, comme le promettait
271
+ déjà le contrat de `build_svg`.
272
+
273
+ ## [0.10.0] — 2026-09-06
274
+
275
+ ### Ajouté
276
+
277
+ - Bus d'intégration : la clé `bus` déclare des relais, et un flux peut en
278
+ traverser un ou plusieurs — `m --> e1 --> e2 --> pas [IMS]`. Le bus est
279
+ dessiné en boîte grise à angles vifs, nom en haut, chaque traversée
280
+ matérialisée par un trait.
281
+ - Détail technique d'un lien : `-(protocole:port)->` dessine un connecteur à
282
+ cheval sur le bord de la boîte où la flèche arrive, deux tiers dedans, un
283
+ tiers dehors. Une entrée déclarée sur un bus appelle une sortie neutre.
284
+ - Clé `type` : `appli` (défaut) ou `appli+tech`. En `appli`, les détails
285
+ techniques écrits dans les flux sont ignorés et les bus restent dessinés —
286
+ la même définition sert donc aux deux lectures.
287
+ - `-->` et `<--` comme synonymes de `->` et `<-`, mieux distingués du tiret
288
+ admis dans un code.
289
+ - Paramètres de rendu des bus (`BUS_*`) et des connecteurs (`CONNECTOR_*`,
290
+ `PORT_*`), dont `CONNECTOR_COLORS`, qui habille les pastilles par protocole,
291
+ et `CONNECTOR_LABEL_GAP`, qui encadre les connecteurs d'une boîte — sous son
292
+ libellé, et au-dessus de sa bordure du bas.
293
+ - Les clés de premier niveau inconnues d'une définition sont signalées : un
294
+ `buss:` mal orthographié ne passe plus en silence.
295
+ - Exemples `examples/bus.yaml` et `examples/technique.yaml`.
296
+ - Éditeur web : deux boutons « Charger » et « Enregistrer » agissant sur le
297
+ panneau affiché, pour lire un fichier local et en produire un. Tout se passe
298
+ dans le navigateur, sans route serveur.
299
+ - Suite de tests JavaScript de l'éditeur web (`tests/js`, exécutée par `node
300
+ --test` et déclenchée depuis `pytest`), avec un DOM de substitution sans
301
+ dépendance npm.
302
+ - Éditeur web : `Tab` indente les lignes d'une sélection multiligne et
303
+ `Maj+Tab` les désindente ; `Échap` relâche le piège clavier, la tabulation
304
+ suivante rend la main au reste de la page.
305
+
306
+ ### Corrigé
307
+
308
+ - Éditeur web : tabuler une sélection de plusieurs lignes la remplaçait par
309
+ deux espaces, effaçant le texte choisi.
310
+ - Éditeur web : la coloration d'une ligne de parenthèses jamais refermées, ou
311
+ d'une longue suite de chiffres, coûtait un temps quadratique et figeait la
312
+ saisie. Les jetons sont bornés, et au-delà de 200 000 caractères le calque
313
+ rend le texte sans coloration.
314
+ - Éditeur web : deux rendus lancés coup sur coup pouvaient revenir dans le
315
+ désordre et afficher l'aperçu périmé.
316
+ - Éditeur web : une réponse serveur illisible, des défauts incomplets ou un
317
+ onglet mal étiqueté échouaient en silence — chacun donne désormais un
318
+ message, ou retombe sur une valeur sûre.
319
+ - Éditeur web : un fichier chargé au format Windows laissait des « \r » dans
320
+ le texte, ce qui brouillait la coloration en fin de ligne.
321
+
322
+ ### Modifié
323
+
324
+ - Le côté d'un flux relayé ne vient plus du sens d'écriture mais d'un
325
+ équilibrage : les bus sont répartis de part et d'autre pour que chaque côté
326
+ porte à peu près autant de flux. Les liens directs gardent la règle
327
+ historique.
328
+ - Une application citée des deux côtés est désormais dessinée **deux fois**,
329
+ une par emplacement, au lieu d'une seule boîte partagée. Seule l'application
330
+ centrale reste unique.
331
+ - Le module `generator` est scindé : `layout` calcule la géométrie, `svg`
332
+ produit le dessin, `generator` porte l'état et l'analyse.
333
+ - `FLOW_GAP` passe de 3 à 0 : la pointe d'une flèche touche désormais ce
334
+ qu'elle vise — bord de rectangle, de boîte de bus ou de pastille.
335
+ - Une largeur unique pour toutes les applications, une autre pour tous les
336
+ bus : deux objets de même nature ne diffèrent plus de taille selon le côté ou
337
+ le rang où ils tombent. Les connecteurs n'élargissent plus leur boîte — elle
338
+ range son nom au-dessus d'eux et grandit en hauteur.
339
+ - L'application centrale est plus large que ses satellites d'un facteur
340
+ `MAIN_WIDTH_RATIO`, 1,2 par défaut. Le canevas d'`examples/minimal.yaml`
341
+ passe donc de 676 à 696 de large.
342
+
343
+ ### Corrigé
344
+
345
+ - Une application émettant **et** recevant n'est plus placée puis replacée : le
346
+ trou vertical qu'elle laissait dans sa première colonne, et les deux dessins
347
+ superposés au même endroit, disparaissent.
348
+
349
+ ## [0.9.0] — 2026-09-06
350
+
351
+ ### Corrigé
352
+
353
+ - Le cœur ne dépend plus d'aucune pile web : elle était installée d'office,
354
+ pour un éditeur qui n'a jamais été qu'un extra. Une installation nue se
355
+ limite désormais à `loguru` et `pyyaml`.
356
+ - L'état du générateur repart de zéro à chaque définition : deux `load_data()`
357
+ successifs ne mêlent plus les applications des deux fichiers, et
358
+ `parse_flows()` appelé deux fois ne double plus les flèches.
359
+ - Les valeurs de configuration sont contrôlées : un entier ou une couleur
360
+ fautifs sont signalés et remplacés par le défaut, au lieu de lever au rendu
361
+ ou d'être interpolés tels quels dans le SVG.
362
+ - Les couleurs sont échappées à l'écriture des attributs SVG.
363
+ - Le trait d'une flèche s'arrête à la base de sa pointe : il la traversait et
364
+ ressortait en bourrelet au-delà.
365
+ - L'éditeur web déclare sa page en route : les visiteurs ne partagent plus les
366
+ mêmes panneaux et le même aperçu.
367
+ - Le libellé d'une application était 6,5 px sous le centre de son rectangle :
368
+ `dominant-baseline` et `TEXT_VERTICAL_OFFSET` se cumulaient.
369
+ - La largeur d'un rectangle tient compte des glyphes du libellé, et non plus
370
+ seulement de leur nombre : un `W` ne comptait pas plus qu'un `i`.
371
+
372
+ ### Ajouté
373
+
374
+ - Tag d'application : `m: Dossier patient !chu` dessine une pastille arrondie sous le nom,
375
+ dans le rectangle. Les couleurs se déduisent de l'application — bordure
376
+ assombrie, fond éclairci — ou se déclarent par nom de tag dans `TAG_COLORS`.
377
+ - Largeur de colonne calée sur le libellé le plus long (`APP_PADDING_X`) : les
378
+ noms d'application ne débordent plus de leur cadre.
379
+ - Restylage du rendu : bordures plus épaisses, angles plus arrondis, marges et
380
+ interlignes plus généreux, pointe de flèche en triangle plein, libellés de
381
+ flux centrés sur leur flèche et détachés du trait par un halo.
382
+ - `FLOW_WIDTH` devient un plancher : la bande de flèches s'élargit à son
383
+ libellé le plus long, qui ne déborde donc plus sur les rectangles.
384
+ - Paramètres de rendu jusqu'ici écrits en dur ou absents :
385
+ `RECT_STROKE_WIDTH`, `FLOW_STROKE_WIDTH`, `APP_FONT_SIZE`, `MAIN_FONT_SIZE`,
386
+ `FLOW_FONT_SIZE`, `LABEL_HALO_WIDTH`, `LABEL_HALO_COLOR`, `FLOW_GAP`.
387
+ - Pile de polices système, avec Arial en dernier recours, au lieu d'Arial seul.
388
+ - `<title>` et `<desc>` sur le SVG, `<title>` sur chaque lien de flux.
389
+ - `SCHEMA_ARCHI_HOST` et `SCHEMA_ARCHI_PORT` pour l'éditeur web.
390
+ - Tests de l'éditeur web (`tests/test_ui.py`), jusqu'ici sans couverture.
391
+ - `docs/publication.md` : comptes et jetons, choix du numéro de version,
392
+ répétition sur TestPyPI, étiquetage et diagnostic des échecs. Le README et
393
+ `docs/formats.md` y renvoyaient sans qu'il existe.
394
+
395
+ ### Modifié
396
+
397
+ - L'éditeur web est réécrit en HTML/CSS/JavaScript servi par FastAPI, à la
398
+ place de NiceGUI : une page statique, une API JSON de quatre routes, et un
399
+ coloriseur maison qui distingue les codes, le sens, le libellé et le lien
400
+ d'un flux. Aucune ressource externe, donc utilisable hors ligne. L'extra
401
+ `ui` installe désormais `fastapi` et `uvicorn`.
402
+ - L'export PNG est proposé dans l'éditeur quand l'extra `png` est présent ;
403
+ l'image `archi-app` l'embarque désormais.
404
+ - Images Docker en deux étages, sans dépendances de développement, uv épinglé
405
+ et exécution sous un utilisateur non privilégié.
406
+
407
+ ### Ruptures
408
+
409
+ Ces changements modifient une sortie existante — régénérer les SVG de
410
+ référence commités ailleurs :
411
+
412
+ - une colonne dont les libellés l'exigent est plus large que `APP_PARAM.width`,
413
+ qui devient une largeur plancher ;
414
+ - un schéma à sens unique ne réserve plus de colonne vide : le bloc central
415
+ démarre à `MARGIN_LEFT` ;
416
+ - `APP_PARAM.padding_top` et `padding_bottom`, inutilisés depuis l'origine,
417
+ sont retirés — les configurations qui les portent restent acceptées, la clé
418
+ est ignorée avec un avertissement.
419
+ - Le restylage change l'apparence **et les dimensions** de tout schéma :
420
+ traits, arrondis, marges, position des libellés. Les valeurs par défaut de
421
+ `RECT_CORNER`, `APP_PARAM.height`, `MARGIN_TOP`, `MARGIN_LEFT`, `HSPACE`,
422
+ `VSPACE`, `FLOW_WIDTH`, `FLOW_MARGIN`, `LINK_LINE_ARROW`, `LABEL_OFFSET_Y` et
423
+ `TEXT_VERTICAL_OFFSET` sont toutes modifiées. Une configuration qui les fixe
424
+ explicitement conserve son rendu d'origine.
425
+ - `LABEL_OFFSET_X` est retiré : le libellé n'est plus décalé depuis le départ
426
+ de la flèche, il est centré dessus.
427
+
428
+ ## [0.7.3] — 2026-07-27
429
+
430
+ Correctifs issus de l'audit de la 0.7.1 par un programme tiers.
431
+
432
+ ### Corrigé
433
+
434
+ - Couleurs de texte configurables : `fill` remplace `color`, sans effet en SVG.
435
+ - Le rectangle de l'application centrale ne dépasse plus le bas du schéma.
436
+ - La CLI retourne `1` quand une définition échoue, et poursuit le lot.
437
+ - La clé `main` redevient facultative (`m` par défaut).
438
+ - `parse_flow` rejette le texte parasite en fin de ligne (`fullmatch`).
439
+ - Les codes d'application acceptent le tiret et le point (`si-rh`, `app.v2`).
440
+ - Le SVG porte un `viewBox` et utilise `dominant-baseline`.
441
+ - Les applications citées dans aucun flux sont signalées en `WARNING`.
442
+ - Seuls les liens `http`, `https`, `mailto` et relatifs donnent une ancre.
443
+ - `split_endpoints` rejette une chaîne portant les deux séparateurs.
444
+
445
+ ### Ajouté
446
+
447
+ - `FLOW_TEXT_COLOR` : couleur du libellé d'un flux, distincte du trait.
448
+ - `Generator.orphan_apps()` : applications rattachées à aucun flux.
449
+
450
+ ### Modifié
451
+
452
+ - La bibliothèque est muette par défaut ; l'appelant fait
453
+ `logger.enable("schema_archi")`.
454
+ - `cli.process_diagram` retourne un `DiagramStatus` au lieu d'un booléen.
455
+
456
+ ### Ruptures
457
+
458
+ Ces changements modifient une sortie existante — régénérer les SVG de
459
+ référence commités ailleurs :
460
+
461
+ - le texte des applications prend la couleur configurée, noir auparavant ;
462
+ - la hauteur du SVG diminue de `MARGIN_TOP` (20 px par défaut) ;
463
+ - `a -> b [x] et voilà` devient une ligne invalide, jusqu'ici tolérée.
464
+
465
+ ## [0.7.1] — 2026-07-27
466
+
467
+ Changement des noms des applications dans l'exemple.
468
+
469
+ ## [0.7.0] — 2026-07-26
470
+
471
+ Première version distribuable sur PyPI. Le projet passe d'un ensemble de
472
+ modules à plat à une bibliothèque installable.
473
+
474
+ ### Ruptures
475
+
476
+ - Les modules à la racine deviennent un paquet `schema_archi` en layout `src/` :
477
+ - `schema_app` → `schema_archi.generator` (la classe `Generator`)
478
+ - `formats` → `schema_archi.formats`
479
+ - `bulk_graph` → `schema_archi.cli`
480
+ - `schema_archi/__init__.py` (dataclasses) → `schema_archi.models`
481
+ - `ui/app-ui.py` → `schema_archi.ui.app`
482
+ - `ui/local_file_picker.py` → `schema_archi.ui.file_picker`
483
+ - `GraphConfig` est déplacée dans `schema_archi.config`.
484
+ - `formats.load_data()` est remplacée par `formats.load_file()`, qui ne
485
+ transforme plus le contenu lu (voir *Corrigé*).
486
+ - `formats.prepare_data()` est renommée `formats.parse_flows_def()`.
487
+ - `formats.from_json()` et `formats.to_json()`, inutilisées, sont supprimées.
488
+ - `Generator.load_config()` et `Generator.set_config()` renvoient désormais un
489
+ booléen indiquant si la configuration a été appliquée.
490
+ - `requires-python` passe de `>=3.14` à `>=3.11`.
491
+ - Suppression du générateur arbre/bus (`schema.py`), des services web
492
+ FastAPI/Flask (`services/`), des interfaces expérimentales à base de tables et
493
+ du sélecteur de fichiers `local_file_picker`, devenu sans appelant.
494
+ - `Generator.graph()` lève `RuntimeError` au lieu d'`AssertionError` lorsque le
495
+ générateur n'est pas initialisé.
496
+ - `Flow.direction` (chaîne `"forward"` / `"backward"`) devient `Flow.is_forward`
497
+ (booléen), et `link` / `position` prennent une valeur par défaut.
498
+ - `Application` n'a plus d'égalité structurelle : deux applications de mêmes
499
+ libellé et code sont désormais distinctes. L'appartenance à une colonne se
500
+ teste en temps constant, sans comparer les flux accumulés.
501
+ - `formats.parse_flows_def()` ne renvoie plus le dictionnaire reçu ; il se
502
+ contente de le modifier sur place.
503
+ - `FORWARD_FLOW` et `BACKWARD_FLOW` passent de `schema_archi.config` à
504
+ `schema_archi.formats` — ils décrivent la syntaxe des définitions, pas le
505
+ rendu. Ils restent exportés depuis `schema_archi`.
506
+ - `Generator.calculate_lane()` devient `_layout_lane()`, privée : c'était une
507
+ étape interne du calcul, jamais destinée à un appel direct. Elle ne renvoie
508
+ plus rien.
509
+ - `Generator._adapt_app_width()` devient `_app_width()` et ne prend plus
510
+ d'argument : le nom de l'application n'était pas utilisé.
511
+
512
+ ### Ajouté
513
+
514
+ - Commandes `schema-archi` (traitement par lot) et `schema-archi-ui` (éditeur web).
515
+ - Extras `png` (cairosvg) et `ui` (nicegui) ; le cœur ne dépend plus que de
516
+ `loguru` et `pyyaml`.
517
+ - Marqueur `py.typed` (PEP 561).
518
+ - Options `--no-png` et `--log-file` sur la ligne de commande.
519
+ - Prise en charge des extensions `.yml` et `.json` en entrée de la CLI.
520
+ - `GraphConfig.from_dict()` ignore les clés inconnues au lieu d'échouer, et
521
+ convertit les listes de couleurs en tuples.
522
+ - Suite de tests pytest (102 tests) remplaçant les scripts ad hoc.
523
+ - Configuration ruff (lint et formatage) dans `pyproject.toml`, couvrant 22
524
+ familles de règles ; le dépôt est sans signalement, et `pyright` non plus.
525
+ - `Generator(apps, flows, main=...)` : le constructeur accepte le code de
526
+ l'application centrale et la définit avant d'analyser les flux.
527
+ - `formats.split_endpoints()` sépare `"a->b"` en source, cible et sens.
528
+ - `GraphConfig.LABEL_OFFSET_X` / `LABEL_OFFSET_Y` remplacent des décalages de
529
+ libellé jusqu'ici codés en dur.
530
+
531
+ - Documentation détaillée : `docs/formats.md` (référence des formats d'entrée,
532
+ grammaire des flux, paramètres de configuration, messages de diagnostic),
533
+ `docs/algorithme.md` (les cinq étapes de la génération, formules de placement,
534
+ exemple chiffré, limites connues) et `docs/publication.md`
535
+ - `examples/minimal.yaml`, le schéma détaillé dans la documentation.
536
+ - `scripts/build-release.sh` : construction de la distribution, contrôles de
537
+ qualité et d'artefacts, essai d'installation hors du dépôt, et publication
538
+ optionnelle sur TestPyPI ou PyPI.
539
+
540
+ ### Corrigé
541
+
542
+ - **L'option `-c/--config` n'avait aucun effet.** `load_config()` passait par un
543
+ chargeur qui exigeait une clé `flows_def`
544
+ - Le fichier de configuration était lui-même traité comme un diagramme, faute
545
+ d'être exclu de la liste des entrées.
546
+ - Le message d'erreur de la CLI mentionnait des formats JSON/TOML alors que
547
+ seul YAML était accepté.
548
+ - `errors.log` était créé dans le répertoire courant à chaque exécution.
549
+ - Le bouton d'enregistrement de l'éditeur web téléchargeait la chaîne littérale
550
+ `"svg_display.content"` au lieu du SVG.
551
+ - `GraphConfig` partageait un même objet `APP_PARAM` entre instances.
552
+ - Les journaux par flux passent de `INFO` à `DEBUG`.
553
+ - **Le SVG produit n'était pas échappé** : une application nommée `R&D` ou un
554
+ libellé contenant `<` suffisait à produire un fichier XML invalide.
555
+ - Les marges du canevas étaient inversées : `HSPACE` s'ajoutait à la hauteur et
556
+ `VSPACE` à la largeur.
557
+ - Les flux dont aucune extrémité n'est l'application centrale disparaissaient
558
+ sans le moindre message.
559
+ - `Generator(apps, flows)` n'analysait rien d'exploitable : `parse_flows()`
560
+ était appelé alors qu'aucune application centrale n'était définie.
appflows-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Frédéric Laurent
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.