Notes de version

Toutes les versions publiées de WUIC Framework, de la plus récente à la plus ancienne, avec les notes complètes de chacune.

Retour aux téléchargements

v1.7.21

Retour à l'index

Version précédente publiée : 1.7.20 (1 octobre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Version consacrée à la sécurité et à l'accès aux données. Elle clôt les constats d'une revue de sécurité complète du framework et amène OData au même niveau de permissions que le CRUD. En résumé :

  • enableCookieAuthentication accepte une troisième valeur, "signed" : cookie signé par le serveur, plusieurs sessions par utilisateur, déconnexion par session ;
  • OData applique les permissions de route et de colonne, les contraintes de ligne de l'utilisateur, et écrit en passant par le CRUD du framework ;
  • les jetons personnels permettent de connecter Power BI, Excel et des scripts aux endpoints OData ;
  • l'option « secure upload » des colonnes d'upload protège de nouveau les fichiers de la colonne ;
  • la modification et la suppression respectent la restriction par utilisateur aussi dans le CRUD de l'interface ;
  • les erreurs affichent à l'utilisateur un message traduit avec un code de suivi, les détails techniques seulement au superadmin.

Les modifications du schéma des métadonnées s'appliquent seules au démarrage. Les fonctionnalités ont été vérifiées par les tests end-to-end sur SQL Server, MySQL, PostgreSQL et Oracle, dans les trois modes de enableCookieAuthentication.


🔐 Authentification et sessions

  • Trois modes. enableCookieAuthentication vaut false, true ou "signed". Avec false l'utilisateur est celui que déclare le cookie du navigateur : réservé au développement. Au démarrage un message [security] le signale, l'éditeur AppSettings le décrit et demande confirmation à l'enregistrement. Une valeur non reconnue vaut "signed", avec un avertissement dans le log.
  • "signed". Le serveur signe le cookie k-user (HMAC-SHA256, expiration dans la signature) : un cookie modifié ou expiré vaut comme absent. Le même utilisateur peut avoir plusieurs sessions ouvertes, chacune avec son identifiant.
  • Déconnexion et révocation. La déconnexion ferme uniquement la session d'où elle part, copies du cookie comprises. La déconnexion d'un utilisateur par un administrateur, la réinitialisation et le changement du mot de passe ferment toutes les sessions de cet utilisateur dans sa société.
  • Durée maximale. Avec signedSessionMaxLifetimeHours (24 par défaut, 0 = sans limite) une session signée expire à cet âge depuis la connexion, même utilisée en continu.
  • Clé de signature. cookie-signing-key est générée au premier démarrage et enregistrée dans appsettings.json. Au démarrage le log affiche l'empreinte de la clé (jamais la clé) et avertit si la clé n'a pas été enregistrée.
  • Appels vérifiés sur le serveur. Avec false le cookie ne porte plus de privilèges forgés (administrateur, rôle, société) : l'utilisateur est relu depuis la base de données.

🔗 OData

  • Permissions. Chaque entity set exige la permission de lecture sur la route. Une colonne refusée à l'utilisateur et citée dans $select, $filter, $orderby ou $expand répond 403 ; sinon elle revient vide.
  • Contraintes de ligne. La requête part du même SELECT que le CRUD avec la restriction par utilisateur, rôle ou société, le filtre par défaut et la suppression logique. $filter, $orderby, $skip, $top et $count s'appliquent à l'extérieur et peuvent seulement restreindre : or 1 eq 1 n'élargit pas le résultat.
  • $expand. Admis vers des routes lisibles sans contraintes de ligne ni suppression logique ; 403 dans les autres cas.
  • Écritures. POST, PATCH et DELETE passent par insertRecord, updateRecord et deleteRecord : permissions, colonnes non modifiables, triggers, champs de journalisation, change log, workflows et suppression logique s'appliquent comme depuis l'interface. Une ligne cachée à l'utilisateur répond 404.
  • Multi-société. La connexion aux données est celle de la société de l'utilisateur, comme dans le CRUD.
  • Découverte. /odata, /odata/$metadata et /odata/openapi.json exigent une session. Avec odataPublicMetadata=true ils redeviennent publics ; les données restent protégées.
  • Jetons personnels. Avec apiTokensEnabled=true chaque utilisateur crée depuis le menu utilisateur (« Jetons API ») des jetons wuic_pat_… avec un nom, une expiration (90 jours par défaut, maximum apiTokenMaxLifetimeDays) et une permission en lecture seule ou aussi en écriture. Ils ne valent que sur /odata, avec les permissions du propriétaire. Power BI et Excel les utilisent comme mot de passe avec des identifiants « Basic » ; les scripts avec Authorization: Bearer. Le jeton n'est affiché qu'une fois ; le superadmin voit et révoque ceux de tous.

🛡️ Sécurité

Hardening best-effort sur toute la surface : contrôles des valeurs qui finissent dans les requêtes (tris, opérateurs, agrégats, clés, filtres numériques) alignés sur les quatre fournisseurs ; chemins d'upload et de rapports confinés dans leurs dossiers ; fonctions d'administration (designer de rapports, suppression et scaffolding des rapports, réordonnancement des colonnes, redémarrage, scaffold OData) réservées au superadmin vérifié en base ; e-mails des workflows seulement par qui peut exécuter le workflow ; données d'exemple des outils pour assistants IA seulement au superadmin et jamais avec des colonnes d'identifiants ; gardes sur les utilisateurs et les rôles liées à la table, pas au nom de la route ; clé publique de licence intégrée au paquet.

📎 Upload

  • « Secure upload » par colonne. Les fichiers d'une colonne avec upload_secure ne se lisent qu'avec une session valide et la colonne visible pour l'utilisateur, depuis /upload comme depuis /api/UploadImage. Les fichiers des autres colonnes restent publics. Les colonnes qui enregistrent le fichier dans la base de données sont protégées par /api/UploadImage.
  • Noms de fichier. Les noms avec des points internes (facture-acme.com.pdf) sont acceptés ; les noms avec des extensions exécutables par le serveur restent refusés même au milieu (photo.aspx.png).

🚦 Erreurs

L'utilisateur reçoit un message traduit avec un code de suivi (bouton « Copier le code » dans le dialogue d'erreur). Le même code est enregistré avec la pile complète dans _error__logs. SQL, piles et messages internes n'arrivent qu'au superadmin. Les traductions des nouveaux messages d'erreur s'ajoutent seules au démarrage.

🐛 Corrections notables

  • Restriction par utilisateur en modification et suppression. L'UPDATE et le DELETE du CRUD ne contenaient que la clé : en connaissant l'id, un utilisateur pouvait modifier la ligne d'un autre. Désormais la ligne doit faire partie de celles que l'utilisateur voit, sinon 403 errors.auth.route_read_forbidden.
  • Filtre par défaut avec des filtres en OR. Avec l'opérateur OR le filtre par défaut de la route disparaissait et la grille montrait les lignes qu'elle devait cacher. Il reste désormais en AND.
  • Oracle. Booléens écrits en 1/0 aussi sur les colonnes de type UI booléen, dans les filtres et dans les paramètres des procédures stockées ; fonctions distinguées des procédures dans le bon schéma ; OData sur le schéma des données même avec l'utilisateur SYSTEM (avant, erreurs ORA-00942 intermittentes).
  • PostgreSQL et Oracle. L'insertion avec une clé identity non envoyée par le client n'échoue plus ; les rapports appliquent les permissions et les filtres de l'utilisateur comme sur SQL Server et MySQL.
  • Premier démarrage sous IIS. La configuration initiale ne renvoie plus de 500 après une installation réussie : les migrations se terminent au redémarrage du worker.
  • Spreadsheet et synchronisation. Avec un filtre actif, la modification et la suppression touchaient la mauvaise ligne ; une sélection au-delà de la page n'atteint plus les enregistrements des pages suivantes ; l'enregistrement par lot du kanban et la synchronisation hors ligne ne réessaient que ce qui a échoué.
  • Menu. La barre apparaît avec les libellés déjà traduits, sans afficher un instant les clés.

📦 Paquets mis à jour

Paquet De À
WuicCore 1.7.20 1.7.21
Wuic.Webcore 1.7.20 1.7.21
WuicOData 1.7.20 1.7.21
RuntimeEfCore 1.7.20 1.7.21
Wuic.MySqlProvider 1.7.20 1.7.21
Wuic.PostgresProvider 1.7.20 1.7.21
Wuic.OracleProvider 1.7.20 1.7.21
wuic-framework-lib (npm) 1.7.20 1.7.21

🔧 Mises à jour opérationnelles recommandées

  1. Mode du cookie : en production, régler enableCookieAuthentication sur "signed" (ou true) ; false est réservé au développement.
  2. Plusieurs instances derrière un répartiteur de charge : copier la même cookie-signing-key sur toutes les instances ; avec des clés différentes, une session ne vaut que sur l'instance qui l'a créée. Vérifier dans le log que l'empreinte coïncide.
  3. Clients OData : les clients qui lisaient $metadata sans session doivent s'authentifier, ou régler odataPublicMetadata=true. Les écritures OData exécutent désormais les triggers et la journalisation du CRUD et, sur les routes avec suppression logique, positionnent l'indicateur au lieu de supprimer la ligne.
  4. md_service_apply_default_filter : obsolète. Le filtre par défaut s'applique toujours, OData compris.
  5. Licence : la surcharge de l'empreinte de la machine se règle uniquement avec la variable d'environnement WUIC_LICENSE_MACHINE_FINGERPRINT ; les clés license-machine-fingerprint-override et license-public-key-pem dans appsettings.json sont ignorées.
  6. Jetons API : pour connecter Power BI, Excel ou des scripts, régler apiTokensEnabled=true (et éventuellement apiTokenMaxLifetimeDays) depuis l'éditeur AppSettings.

v1.7.20

Retour à l'index

Version précédente publiée : 1.7.18 (1 octobre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Version corrective : elle rassemble les défauts apparus en développant une application avec les cinq patterns de développement documentés, à partir du projet d'exemple des paquets sources, et accélère le moteur RAG sur les machines sans GPU. Elle contient aussi les corrections de la 1.7.19, publiée uniquement sous forme de paquets NuGet et npm : ces notes couvrent les deux. En résumé :

  • relancer le scaffolding avec « Create Menu » ne duplique plus l'entrée de menu ;
  • sous PostgreSQL et Oracle, le tri côté serveur demandé par la grille est appliqué, y compris quand la liste place un enregistrement mis en avant en tête ;
  • avec ng serve, les exports se téléchargent aussi depuis le serveur de développement ;
  • les recherches du moteur RAG sur CPU sont jusqu'à environ trois fois plus rapides sur les machines avec peu de cœurs ;
  • les pages des cinq patterns de développement contiennent des exemples de code qui compilent, dans les cinq langues.

Aucune modification des métadonnées, des traductions ou du schéma de la base de données : la mise à jour ne nécessite aucun script.


🗄️ Fournisseurs PostgreSQL et Oracle

  • Tri côté serveur. Avec les opérations côté serveur activées, le tri choisi sur une colonne de la grille n'atteignait pas la requête : les enregistrements revenaient toujours triés par clé primaire, même en demandant un ordre décroissant sur un autre champ. Le ORDER BY utilise désormais les colonnes demandées et n'ajoute la clé primaire qu'en dernier critère, comme sous SQL Server et MySQL.
  • Tri avec un enregistrement mis en avant. Quand la liste place un enregistrement précis en tête, le tri demandé était encore ignoré dans la 1.7.19. L'ordre est désormais : enregistrement mis en avant, colonnes demandées, clé primaire.

🤖 Moteur RAG

  • Recherches plus rapides sur CPU. Sans GPU, les threads de calcul des modèles restaient actifs en attente entre deux opérations, et le préchauffage du cache en arrière-plan tournait en parallèle de la première recherche : sur les machines avec peu de cœurs, ils se disputaient le CPU. Les threads n'attendent plus de façon active et les calculs des modèles s'exécutent un par un dans le processus. Les recherches (chat et outils MCP) sont jusqu'à environ trois fois plus rapides sur les machines avec peu de cœurs, et la première recherche n'est plus ralentie par le préchauffage en cours. Sur les PC disposant de cœurs libres, les temps ne changent pas.

🐛 Corrections notables

  • Entrée de menu dupliquée au scaffolding. Relancer « Scaffold Table » ou « Scaffold View » avec « Create Menu » sur une table ou une vue déjà générée ajoutait une deuxième entrée de menu pour la même route. L'entrée n'est désormais créée que si la route n'en a pas encore.
  • Exports avec le serveur de développement. Dans le projet client des paquets sources, proxy.conf.js ne transmettait pas le chemin /Tmp_export au backend : avec ng serve, le lien du fichier exporté (Excel, CSV, PDF) renvoyait la page de l'application au lieu du fichier. Le chemin est désormais transmis et le téléchargement fonctionne comme dans l'installation publiée.

📚 Documentation

Les pages des cinq patterns de développement ont été corrigées dans toutes les langues :

  • Framework + manuel : l'exemple passe la source de données avec [hardcodedDatasource] et définit [autoload]="true" ; sans autoload, la liste ne charge que le schéma, pas les enregistrements.
  • Données du framework + composant personnalisé : nouvel exemple de setCurrent, addNewRecord, syncData et fetchData appelés depuis le composant personnalisé.
  • Composant du framework + données personnalisées : les filtres côté client construisent un filtre par colonne, tel que la list-grid le lit.
  • Full custom : le composant déclare les imports nécessaires (TableModule, CheckboxModule, ButtonModule, FormsModule).
  • Full autogeneration : le tableur requiert la fonctionnalité sous licence (sans elle, la route s'ouvre en liste) ; le dashboard n'est pas un archétype de route et la page ne le cite plus parmi les pages générées.

La documentation est incluse dans la bibliothèque npm et publiée sur le site.

📦 Paquets mis à jour

Paquet De À
WuicCore 1.7.18 1.7.20
Wuic.Webcore 1.7.18 1.7.20
WuicOData 1.7.18 1.7.20
RuntimeEfCore 1.7.18 1.7.20
Wuic.MySqlProvider 1.7.18 1.7.20
Wuic.PostgresProvider 1.7.18 1.7.20
Wuic.OracleProvider 1.7.18 1.7.20
wuic-framework-lib (npm) 1.7.18 1.7.20

Si vous avez déjà mis à jour les paquets en 1.7.19, la 1.7.20 apporte en plus le tri avec un enregistrement mis en avant, le moteur RAG plus rapide et la correction de la page du pattern full autogeneration.

🔧 Mises à jour opérationnelles recommandées

  1. Projets issus des paquets sources : la mise à jour des paquets n'écrase pas le proxy.conf.js du projet. Ajouter l'entrée '/Tmp_export' avec la même configuration que les autres entrées vers le backend (ou la copier depuis le proxy.conf.js du paquet), puis redémarrer ng serve.
  2. Menus dupliqués : si relancer le scaffolding avec une version précédente a laissé des entrées de menu en double, supprimer les entrées en trop depuis la gestion du menu.
  3. PostgreSQL et Oracle : aucune action ; après la mise à jour, les grilles avec opérations côté serveur trient comme demandé.
  4. Moteur RAG : aucune action ; le moteur mis à jour se trouve dans le dossier rag-engine du paquet et la correction s'applique à l'exécution sur CPU.

v1.7.18

Retour à l'index

Version précédente publiée : 1.7.17 (30 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Version corrective : elle rassemble les défauts apparus en installant la 1.7.17 depuis zéro sur des machines propres, avec les quatre bases de données prises en charge. En résumé :

  • les outils MCP de recherche ne tombent plus en timeout pendant le chargement du moteur RAG ;
  • sous PostgreSQL le moteur RAG se charge de nouveau tout seul après le démarrage ;
  • sous Oracle XE 21c le scaffolding des tables et des vues écrit de nouveau les métadonnées, y compris au premier démarrage ;
  • les stack traces envoyées par le crash reporting sont reconstruites en entier.

Aucune modification des métadonnées, des traductions ni du schéma de la base de données : la mise à jour ne demande aucun script.


⚠️ Comportements qui changent

  • Outils MCP pendant le chargement du moteur. wuic_codebase_search et wuic_ask attendent jusqu'à 30 secondes (auparavant 60) que le moteur RAG soit prêt ; s'il ne l'est toujours pas, ils répondent par une erreur qui demande de réessayer dans environ 60 secondes. Le chargement continue sur le backend, et l'appel répété trouve le moteur prêt.

🤖 Moteur RAG

  • Timeout des outils MCP. Pendant le chargement du moteur, le serveur MCP lançait une recherche de préchauffage qui s'exécutait en parallèle de la vraie recherche : sur une machine sans GPU les deux se ralentissaient mutuellement et l'appel dépassait les 120 secondes d'attente du client, sous Windows aussi. Désormais le serveur MCP se limite à lancer le chargement et à l'attendre, et la vraie recherche dispose de tout le temps du client.
  • /api/Rag/Health lance toujours le chargement. L'endpoint lance le chargement du moteur en arrière-plan même lorsqu'il ne trouve aucun utilisateur administrateur à qui notifier la progression : dans ce cas le moteur se charge sans notifications.
  • PostgreSQL. La recherche de l'administrateur échouait sous PostgreSQL, où isAdmin est un champ boolean : le moteur ne démarrait jamais depuis /api/Rag/Health et les outils MCP restaient « en chargement ». Désormais l'administrateur est trouvé et le moteur démarre comme sur les autres bases de données.

🗄️ Fournisseur Oracle

  • Scaffolding sous Oracle XE 21c. Les versions récentes du pilote Oracle envoient les valeurs true/false comme type BOOLEAN, qu'Oracle avant la 23 refuse (ORA-00932). Le scaffolding des tables et des vues (depuis l'interface et au premier démarrage) répondait par une erreur, et le premier démarrage se terminait sans les métadonnées des tables applicatives. Désormais les flags des métadonnées s'écrivent en 0/1, que les colonnes NUMBER des tables de métadonnées acceptent sur toutes les versions d'Oracle.

🐛 Corrections notables

  • Crash reporting, stack traces illisibles. Avec CrashReporting:Enabled=true les stack traces envoyées par les installations n'étaient pas reconstruites sur le receiver : les noms internes du framework restaient illisibles et l'analyse des plantages en pâtissait. À partir de la 1.7.18 les rapports sont reconstruits en entier. Aucune modification de la configuration ni des données envoyées.

📦 Paquets mis à jour

Paquet De À
WuicCore 1.7.17 1.7.18
Wuic.Webcore 1.7.17 1.7.18
WuicOData 1.7.17 1.7.18
RuntimeEfCore 1.7.17 1.7.18
Wuic.MySqlProvider 1.7.17 1.7.18
Wuic.PostgresProvider 1.7.17 1.7.18
Wuic.OracleProvider 1.7.17 1.7.18
wuic-framework-lib (npm) 1.7.17 1.7.18

🔧 Mises à jour opérationnelles recommandées

  1. Assistants de code avec le serveur MCP WUIC : sur une installation existante le workspace contient la copie précédente de scripts/mcp/wuic-rag-mcp.mjs. La remplacer par celle du paquet (llm-workspace/templates/app-llm-workspace/scripts/mcp/) ou régénérer le workspace comme décrit dans llm-workspace/README.md, puis redémarrer le client MCP.
  2. Oracle XE 21c : si un premier démarrage avec la 1.7.17 ou une version antérieure s'est terminé sans les métadonnées des tables applicatives, refaire le scaffolding de ces tables depuis l'interface après la mise à jour.
  3. Crash reporting : ceux qui l'utilisent n'ont rien à faire ; les rapports des versions précédentes restent tels quels, les nouveaux sont lisibles en entier.

v1.7.17

Retour à l'index

Version précédente publiée : 1.7.16 (29 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Version corrective : elle rassemble les défauts apparus en installant la 1.7.16 depuis zéro sur des machines propres, Windows et Linux. En résumé :

  • la carte ne charge plus Google Maps avec une fausse clé quand aucune clé n'a été configurée ;
  • le moteur RAG se charge beaucoup plus vite à la première utilisation, et peut être chargé au démarrage ;
  • les outils MCP de recherche attendent le moteur au lieu d'expirer ;
  • l'AppSettings Editor s'ouvre en quelques secondes ;
  • le row template de la list-grid ne se casse plus au premier chargement direct d'une page.

Aucune modification des métadonnées, des traductions ou du schéma de la base de données : la mise à jour ne nécessite aucun script.


⚠️ Comportements qui changent

  • Clé Google Maps non configurée. La valeur d'installation __SET_GOOGLE_MAPS_API_KEY__, si elle n'a pas été remplacée, vaut désormais clé absente : la carte affiche l'avertissement de clé manquante. Auparavant le navigateur chargeait Google Maps avec ce texte comme clé (InvalidKeyMapError et erreurs internes de Google dans la console). Cela vaut pour toute valeur de la forme __SET_...__ dans GoogleMaps:ApiKey.
  • Outils MCP pendant le chargement du moteur. wuic_codebase_search et wuic_ask attendent jusqu'à 60 secondes que le moteur RAG soit prêt ; s'il ne l'est pas encore, ils répondent par une erreur qui demande de réessayer dans environ 60 secondes, au lieu de laisser expirer l'appel du client.

🤖 Moteur RAG

  • Première utilisation plus rapide. Le préchauffage du moteur après le chargement exécutait une recherche complète, environ 35 passes du reranker : sur une machine Linux sans GPU, il représentait environ 133 des 139 secondes du chargement à froid. Il fait désormais une seule passe de l'embedder et une du reranker sur un texte court. Les résultats des recherches ne changent pas.
  • Chargement au démarrage, facultatif. Nouvelle clé AppSettings:rag-engine-eager-load (par défaut false). Avec true, si les modèles sont déjà téléchargés, le backend charge le moteur en arrière-plan au démarrage, sans notifications, et la première recherche (chat ou MCP) ne paie pas le chargement à froid. Le coût est la RAM du moteur, 4,5-6,5 Go, occupée même si le RAG n'est pas utilisé. Avec false le moteur se charge à la première requête, comme avant.
  • Serveur MCP. L'attente du moteur se trouve dans le serveur MCP que le premier démarrage installe dans le workspace pour les assistants de code (scripts/mcp/wuic-rag-mcp.mjs). Pendant l'attente, le serveur lance lui-même le chargement du moteur sur le backend.

🐛 Corrections notables

  • AppSettings Editor lent à s'ouvrir. Avec beaucoup de clés, l'éditeur pouvait mettre des dizaines de secondes à apparaître après la réponse du serveur, car chaque frappe ou mise à jour d'un champ texte revérifiait tout l'éditeur et recalculait tous les libellés traduits. Désormais chaque champ texte se met à jour seul et les libellés sont calculés une seule fois : l'ouverture descend à quelques secondes.
  • List-grid, row template au premier chargement. En ouvrant directement l'URL d'une page avec une list-grid alimentée par un datasource qui répond tout de suite (endpoint personnalisé, hardcodedDatasource), les données pouvaient arriver avant que l'application ne publie les imports du row template (gridRowImports). Le template compilé sans ces pipes restait en cache et les lignes ne s'affichaient pas (en production, erreur onDestroy sur undefined). La grid compile désormais le row template après la publication des imports ; si l'application ne les publie jamais, elle compile sans eux au bout de 10 secondes, comme avant.

📦 Paquets mis à jour

Paquet De À
WuicCore 1.7.16 1.7.17
Wuic.Webcore 1.7.16 1.7.17
WuicOData 1.7.16 1.7.17
RuntimeEfCore 1.7.16 1.7.17
Wuic.MySqlProvider 1.7.16 1.7.17
Wuic.PostgresProvider 1.7.16 1.7.17
Wuic.OracleProvider 1.7.16 1.7.17
wuic-framework-lib (npm) 1.7.16 1.7.17

🔧 Mises à jour opérationnelles recommandées

  1. Cartes : vérifier que GoogleMaps:ApiKey contient une vraie clé. S'il contient encore __SET_GOOGLE_MAPS_API_KEY__, après la mise à jour les cartes affichent l'avertissement de clé manquante : c'est le comportement attendu tant que la clé n'est pas configurée.
  2. RAG sur serveurs dédiés : si vous utilisez le chat ou les outils MCP juste après chaque redémarrage et disposez d'assez de RAM, définir "rag-engine-eager-load": "true" dans AppSettings. Sur les machines partagées, garder la valeur par défaut.
  3. Assistants de code avec le serveur MCP WUIC : sur une installation existante, le workspace contient la copie précédente de scripts/mcp/wuic-rag-mcp.mjs. Pour bénéficier de l'attente du moteur, la remplacer par celle du paquet (llm-workspace/templates/app-llm-workspace/scripts/mcp/) ou régénérer le workspace comme décrit dans llm-workspace/README.md. Un client qui reçoit la demande de réessayer doit simplement répéter l'appel.

v1.7.16

Retour à l'index

Version précédente publiée : 1.7.15 (28 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Cette version corrige les défauts révélés par un test de charge à 100 utilisateurs sur les quatre bases de données installées sous Linux, et réduit le travail que le serveur effectue pour chaque requête. En résumé :

  • colonnes géographiques écrites correctement sur Oracle et PostgreSQL, avec des formats de point documentés et une erreur 400 pour les valeurs invalides ;
  • un texte plus long que la colonne répond 400 au lieu de 500 ;
  • Oracle nettement plus rapide sous charge ;
  • limite des tentatives de login par IP configurable.

Comment elle a été vérifiée. 100 utilisateurs virtuels pendant 10 minutes (listes, filtres, tris, insertions, modifications, suppressions, import, export, rapports) sur SQL Server, MySQL, PostgreSQL et Oracle Free, chacun sur Ubuntu 24.04 avec nginx : entre 11 340 et 11 490 opérations par base de données, 0 erreur HTTP et aucune ligne dans le journal d'erreurs de l'application. Lorsqu'un point a été vérifié autrement, c'est indiqué.


⚠️ Comportements qui changent

  • Limite de login par IP désactivée par défaut. Jusqu'à la 1.7.15 elle était fixée à 30 tentatives par minute et par IP. Désormais c'est loginRateLimitPerIpPerMinute qui s'applique, par défaut 0 (désactivée). La limite par utilisateur (5 mots de passe erronés en 5 minutes) reste toujours active. Sur les installations exposées à internet, configurer 30.
  • Position invalide refusée. Une valeur d'une colonne point dans un format non reconnu répond désormais HTTP 400 errors.input.geo_point.invalid et l'enregistrement n'est pas sauvegardé. Auparavant SQL Server et MySQL enregistraient NULL sans erreur, Oracle et PostgreSQL répondaient 500. Une valeur vide enregistre NULL comme avant.
  • Texte trop long : 400. Un texte plus long que la colonne physique répond HTTP 400 errors.input.value_too_long (ou errors.input.value_too_long.column avec args.column, lorsque la base de données nomme la colonne) au lieu de 500 errors.db.sql_exception.
  • Dernière activité de la session. LastActivityDate est mise à jour au plus une fois par minute et par utilisateur, et non plus à chaque requête. L'expiration de la session peut se décaler d'au plus 60 secondes.
  • Cache de sys_info sur toutes les bases de données. Auparavant seul SQL Server gardait la ligne en cache pendant 5 secondes ; désormais MySQL, PostgreSQL et Oracle aussi. Une modification faite de l'extérieur (SQL à la main, un autre nœud) est visible sous 5 secondes, et une augmentation de project_metadata_version faite par un autre nœud vide désormais les caches des métadonnées sur ces trois bases de données aussi.
  • Oracle, nouvelles installations. Le premier démarrage crée dans chaque schéma chargé le trigger de logon WUIC_SESSION_CURSOR_SHARING (voir la section Oracle).

🛡️ Sécurité

Best-effort hardening : limite des tentatives de login par IP configurable (loginRateLimitPerIpPerMinute, réponse HTTP 429 errors.auth.login_rate_limited avec retryAfterSeconds) avec une liste d'IP exemptées (loginRateLimitExemptIps, IP séparées par des virgules, traitées comme le loopback : jamais limitées ni comptées), toutes deux lues à chaque login ; sur PostgreSQL et Oracle, les requêtes qui lisent utilisateurs et rôles par id, nom d'utilisateur ou email passent les valeurs en paramètres au lieu de les concaténer dans le texte SQL.

🗺️ Colonnes géographiques

  • Oracle : toute insertion ou modification avec une colonne point ou geometry renseignée échouait (ORA-50028), car le provider écrivait la syntaxe de SQL Server. Désormais la valeur est convertie en WKB (SRID 0, le même format que les données du tutoriel) et passée en paramètre.
  • PostgreSQL : même défaut, toute insertion ou modification avec une position renseignée échouait. Désormais la valeur est écrite avec ST_GeomFromText (SRID 0).
  • Formats acceptés pour les colonnes point : JSON {"lat": 45.4642, "lng": 9.19} (aussi lon/long), paire 45.4642, 9.19 (latitude, longitude), WKT POINT(9.19 45.4642) (longitude, latitude), texte Lat: 45.4642, Long: 9.19. Le séparateur décimal est le point. En lecture la position revient toujours en JSON.
  • Valeurs invalides : HTTP 400 errors.input.geo_point.invalid avec la colonne et la valeur reçue. Sur Oracle les colonnes geometry acceptent le WKT POINT, POLYGON et MULTIPOLYGON à deux dimensions ; un WKT invalide répond errors.input.geo_wkt.invalid. Messages traduits dans les 5 langues.

Vérification : un test end-to-end sur les quatre bases de données insère et modifie une position dans chacun des quatre formats et la relit avec les coordonnées attendues, vérifie qu'une valeur invalide est refusée avec 400 sans toucher la donnée et qu'une valeur vide enregistre NULL.

🗄️ Oracle sous charge

  • Premier démarrage : après le chargement de chaque schéma, le framework crée le trigger de logon WUIC_SESSION_CURSOR_SHARING, qui règle CURSOR_SHARING = FORCE pour les sessions de l'application, et collecte les statistiques du schéma (DBMS_STATS.GATHER_SCHEMA_STATS). Si l'une des deux étapes échoue, l'erreur est écrite dans le journal et le premier démarrage continue.
  • Authentification : l'id utilisateur est comparé à la colonne sans TO_CHAR, donc Oracle utilise l'index de la clé au lieu de lire toute la table des utilisateurs à chaque requête.
  • Lecture des colonnes spatiales : le BLOB est converti en JSON ou WKT dans le serveur d'application après la lecture, et non plus par une fonction PL/SQL exécutée ligne par ligne.
  • Clé MAX : avec des insertions simultanées sur des tables parent et enfant, le bloc qui calcule la clé pouvait finir en deadlock (ORA-00060). Il réessaie désormais jusqu'à 3 fois.

Mesuré avec la même charge, avant et après ces modifications (y compris celles de la section suivante), sur une installation existante où trigger et statistiques ont été appliqués à la main : temps de base de données passé dans les instructions SQL de 794 à 61 secondes, hard parses de 73 719 à 7 379, CPU d'Oracle au 95e percentile de 26,5 % à 6,4 %. Au 95e percentile les listes passent de 1,6 s à 0,16 s, la lecture d'un enregistrement de 1,28 s à 68 ms, getTableMetadata de 1,95 s à 0,32 s.

⚡ Moins de travail par requête

  • sys_info : la ligne était relue environ 7 fois par requête sur MySQL, PostgreSQL et Oracle (sur MySQL 23,7 % du temps de la base de données dans le test de charge). Désormais elle est lue au plus une fois toutes les 5 secondes par tenant, sur toutes les bases de données.
  • LastActivityDate : l'UPDATE à chaque requête authentifiée représentait 34,7 % du temps de la base de données sur MySQL. Désormais il s'exécute au plus une fois par minute et par utilisateur, sur toutes les bases de données ; les secondes depuis la dernière activité sont calculées par la base de données, avec sa propre horloge.
  • PostgreSQL : au premier démarrage, après le chargement des scripts, le framework exécute ANALYZE, afin que les premières requêtes ne soient pas planifiées sans statistiques. L'installeur Linux fait de même.
  • Rapports : chaque impression écrivait une ligne "report call" dans le journal d'erreurs (_error__logs). Ce n'est plus le cas.

🐛 Corrections notables

  • PostgreSQL, filtres sur colonnes boolean : un filtre sur une colonne boolean native échouait avec 42883: operator does not exist: boolean = integer.
  • PostgreSQL, erreurs SQL dans les listes : elles arrivent au client en errors.db.sql_exception avec le code SQLSTATE, au lieu de errors.server.unhandled.
  • Change log des suppressions et modifications : sur MySQL le change log des suppressions n'était jamais écrit. Sur MySQL et SQL Server la date était passée en texte et la conversion dépendait de la langue du serveur (sur SQL Server sous Linux elle échouait à chaque suppression). La date est désormais un paramètre typé.
  • Uploads stockés dans la base de données : modifier un enregistrement avec une colonne d'upload en base dont le nom contient des majuscules échouait sur PostgreSQL (42703). Le nom de la colonne est désormais entre guillemets, et il en va de même sur MySQL et SQL Server.
  • MySQL, tri par défaut : sur une table sans clé dans les métadonnées, la liste était triée sur la première colonne même spatiale ou binaire, avec Out of sort memory. Les colonnes spatiales et binaires sont désormais exclues.
  • MySQL, index des métadonnées : le script qui crée les index sur les routes et les colonnes des métadonnées échouait à chaque démarrage et les index n'étaient jamais créés. Ils sont désormais créés au démarrage.
  • Longueur maximale dans les métadonnées : mc_max_length des colonnes nvarchar/nchar était enregistrée en octets, soit le double des caractères : dans les formulaires on pouvait saisir jusqu'au double des caractères et l'enregistrement échouait ensuite. Le scaffolding enregistre désormais des caractères et, dans les scripts du premier démarrage, les longueurs sont les longueurs physiques : 127 colonnes corrigées dans le tutoriel SQL Server (y compris les vues du tutoriel et des tables système comme _mail_recipients, _mailing_lists, _notifications, _wuic_workflow_instance_log et scheduler_execution), 21 dans le profil minimal SQL Server, 41 sur MySQL, 34 sur PostgreSQL et 34 sur Oracle. Le contrôle de la longueur maximale dans les formulaires correspond désormais à la colonne.
  • Tutoriel, archive des températures : sur SQL Server la première page de la liste de Warehouse.ColdRoomTemperatures_Archive (3,65 millions de lignes) dépassait le délai sous charge. Deux index créés au démarrage la font passer de 5,4 s à 6 ms (mesuré sur SQL Server sous Linux). Sur MySQL, PostgreSQL et Oracle un index sur la clé est créé au démarrage ; le cas n'y a pas été mesuré.

🐧 Installeur Linux

  • nginx : worker_connections 4096, worker_rlimit_nofile 16384, et connexions keep-alive vers Kestrel au lieu d'une nouvelle connexion pour chaque requête (WebSocket inchangés).
  • Bases de données : MySQL et PostgreSQL avec 300 connexions et buffers à 25 % de la RAM (entre 128 Mo et 8 Go), Oracle Free avec PROCESSES 400 (un redémarrage du conteneur pendant l'installation). SQL Server reste en édition Express.
  • Ces valeurs visent quelques centaines d'utilisateurs : à 100 utilisateurs les valeurs par défaut suffisaient encore (MySQL 59 connexions sur 151, Oracle 148 processus sur 200). Le test de charge décrit plus haut a tourné avec les valeurs précédentes ; ces étapes de l'installeur n'ont pas encore été testées sur une installation à partir de zéro.
  • Une installation existante conserve les valeurs précédentes. Les commandes pour les relever à la main sont dans le README du tarball Linux, section "Capacity for hundreds of concurrent users".

📦 Paquets mis à jour

Paquet De À
WuicCore 1.7.15 1.7.16
Wuic.Webcore 1.7.15 1.7.16
WuicOData 1.7.15 1.7.16
RuntimeEfCore 1.7.15 1.7.16
Wuic.MySqlProvider 1.7.15 1.7.16
Wuic.PostgresProvider 1.7.15 1.7.16
Wuic.OracleProvider 1.7.15 1.7.16
wuic-framework-lib (npm) 1.7.15 1.7.16

🔧 Mises à jour opérationnelles recommandées

  1. Installations exposées à internet : configurer dans AppSettings "loginRateLimitPerIpPerMinute": "30", la valeur fixe de la 1.7.15. Pour les tests de charge depuis une seule IP, ajouter cette IP à loginRateLimitExemptIps.
  2. Clients qui gèrent les codes d'erreur : un texte trop long et une position invalide arrivent désormais en HTTP 400 avec les codes errors.input.value_too_long, errors.input.value_too_long.column et errors.input.geo_point.invalid. Sur toutes les bases de données, les nouvelles installations ont les messages des quatre nouveaux codes (errors.input.geo_point.invalid, errors.input.geo_wkt.invalid, errors.input.value_too_long, errors.input.value_too_long.column) traduits dans les 5 langues ; sur une installation existante, le message de secours s'affiche tant que les traductions ne sont pas ajoutées depuis la gestion des traductions de l'interface.
  3. Oracle, installations existantes : pour obtenir le trigger et les statistiques des nouvelles installations, exécuter en tant qu'utilisateur de chaque schéma (données et métadonnées) :
    CREATE OR REPLACE TRIGGER WUIC_SESSION_CURSOR_SHARING AFTER LOGON ON SCHEMA
    BEGIN EXECUTE IMMEDIATE 'ALTER SESSION SET CURSOR_SHARING = FORCE';
    EXCEPTION WHEN OTHERS THEN NULL; END;
    /
    BEGIN DBMS_STATS.GATHER_SCHEMA_STATS(ownname => SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA')); END;
    /
    
    Pour revenir au comportement précédent : DROP TRIGGER WUIC_SESSION_CURSOR_SHARING.
  4. Linux avec de nombreux utilisateurs simultanés : sur une installation existante, relever les limites de nginx et de la base de données avec les commandes du README du tarball Linux.
  5. Tutoriel sur SQL Server : le premier démarrage après la mise à jour construit deux index sur Warehouse.ColdRoomTemperatures_Archive (15 à 25 secondes chacun, mesurés) : ce démarrage dure plus longtemps, une seule fois.
  6. Plusieurs nœuds sur la même base de données : les modifications de sys_info faites par un nœud arrivent aux autres sous 5 secondes.
  7. Longueurs dans les métadonnées, installations existantes : les métadonnées déjà présentes ne sont pas corrigées automatiquement. Pour les aligner, relancer le scaffolding de la table ou fixer mc_max_length de la colonne au nombre de caractères.

v1.7.15

Retour à l'index

Version précédente publiée : 1.7.14 (25 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Cette version corrige les défauts révélés par le test de charge de la 1.7.14 et par une campagne de tests sur des installations propres des quatre bases de données (SQL Server, MySQL, PostgreSQL, Oracle). En résumé :

  • l'ouverture d'une route est environ dix fois plus rapide sous charge ;
  • les clés MAX ne produisent plus de doublons lors d'insertions simultanées, et sur SQL Server un export ne bloque plus les écritures ;
  • l'import et l'export sont portables entre bases de données, avec des défauts corrigés sur Oracle et PostgreSQL ;
  • la déconnexion sur Oracle ferme désormais réellement la session.

🛡️ Sécurité

Déconnexion sur Oracle. Sur Oracle, la déconnexion n'invalidait pas le jeton de session : après la déconnexion, le même cookie pouvait encore lire les données. La déconnexion ferme désormais la session sur Oracle aussi. Les utilisateurs d'Oracle devraient mettre à jour.

⚡ Performances

Métadonnées à l'ouverture d'une route. La lecture des métadonnées d'une route (getTableMetadata) est environ dix fois plus rapide. Les permissions par utilisateur, rôle et société sont évaluées sans compiler une expression pour chaque colonne, et la sérialisation réutilise sa configuration au lieu de la reconstruire à chaque appel. Le résultat ne change pas : mêmes permissions, même JSON.

Sur le serveur de démonstration (SQL Server, 100 utilisateurs simultanés) le 95e percentile de l'appel est passé de 2,4-4,5 s à 0,2-0,4 s, et le 95e percentile du CPU du processus de 54 % à 31 %.

🔑 Clé primaire MAX

Sur les routes avec md_primary_key_type = "MAX" la clé d'une nouvelle ligne est le maximum + 1. Jusqu'à la 1.7.14 le maximum était lu par une requête séparée de l'insert : deux utilisateurs qui enregistraient au même instant pouvaient recevoir la même clé, et le second enregistrement échouait sur une violation de clé primaire.

  • Le maximum est désormais calculé dans l'insert, avec un verrou sur la table jusqu'au commit : les insertions simultanées reçoivent des clés consécutives.
  • Cela vaut aussi pour la « clé dépendante » des clés composées (maximum + 1 pour chaque valeur de la clé parente).
  • Cela vaut pour l'insertion depuis le formulaire, la duplication d'un enregistrement et l'import Excel.
  • Le mécanisme de verrou dépend de la base de données : UPDLOCK, HOLDLOCK sur SQL Server, SELECT ... FOR UPDATE sur MySQL, un advisory lock de transaction sur PostgreSQL, LOCK TABLE ... IN EXCLUSIVE MODE sur Oracle.

Un import qui insère de nouvelles lignes dans une table à clé MAX garde le verrou jusqu'à la fin du fichier : pendant ce temps les autres insertions sur la même table attendent, et sur Oracle aussi les modifications et suppressions.

📤 Export sur SQL Server

Un export lit la table pendant tout le temps où il écrit le fichier. Avec l'isolation par défaut de SQL Server cette lecture bloquait les insertions et modifications sur la même table jusqu'à la fin de l'export (mesuré : un update en attente pendant 5,5 s lors de l'export de 70 000 lignes).

  • Si la base de données a ALLOW_SNAPSHOT_ISOLATION ON, l'export lit en isolation snapshot et les écritures n'attendent plus (même update : environ 100 ms). Le fichier contient les mêmes données.
  • L'option ne vaut que pour l'export : les autres lectures ne changent pas de comportement. Elle coexiste avec READ_COMMITTED_SNAPSHOT ON.
  • Sans l'option l'export fonctionne comme avant.
  • La base de données du tutoriel est créée avec READ_COMMITTED_SNAPSHOT ON, ce qui supprime le même blocage pour les lectures des grilles.

📥 Import et export entre bases de données

  • Oracle, lookups dans l'export. Dans les colonnes lookup l'export écrivait la clé au lieu de la description (par exemple 16 au lieu du nom de la personne). Le fichier ne se réimportait pas : « no record of 'people' has this description ». L'export écrit désormais la description, et le cycle export → modification → import fonctionne sur Oracle comme sur les autres bases.
  • PostgreSQL, import. Chaque import qui cherchait des lignes existantes par clé échouait avec 42883: operator does not exist: integer = text. La clé lue dans le fichier est désormais convertie dans le type de la colonne.
  • En-têtes portables. La colonne clé d'un lookup (mode clé + description) et les parenthèses qui distinguent deux colonnes de même libellé utilisent désormais le nom de la colonne dans les métadonnées WUIC, identique sur toutes les bases, et non le nom physique (sur Oracle en majuscules, par exemple CONTACTPERSONID). Un fichier exporté depuis une base se réimporte dans une autre. Les fichiers exportés avant, avec le nom physique, se réimportent comme avant.

🌐 Page « Traductions des données »

La page d'administration des traductions des enregistrements (_record_field_translations) affiche désormais les traductions enregistrées, avec les noms de table et d'utilisateur, sur les quatre bases de données.

  • MySQL : la liste répondait avec une erreur de la base de données.
  • Oracle : la liste échouait avec ORA-00942, car les tables des utilisateurs et des métadonnées se trouvent dans un autre schéma. Le framework qualifie désormais le schéma et accorde à l'utilisateur des données le SELECT nécessaire à la première utilisation.
  • PostgreSQL : la liste lisait la mauvaise table et n'affichait pas les traductions enregistrées. Elle lit désormais celle de la base de données applicative. PostgreSQL ne joignant pas des tables de bases différentes, les noms d'utilisateurs et de tables sont lus par une requête séparée. Le tri et le regroupement sur ces colonnes portent sur la clé.

🗄️ Oracle

  • Réinstallation sur une base existante. Au premier démarrage, la confirmation de recréer la base échouait avec ORA-01940 si l'utilisateur avait encore des sessions ouvertes. Les sessions sont désormais fermées et attendues avant le DROP USER.
  • Métadonnées du tutoriel. Les métadonnées du tutoriel Oracle sont alignées sur celles de SQL Server : descriptions des lookups et autres propriétés des colonnes. Cela vaut pour les nouvelles installations du tutoriel.

🐛 Corrections notables

  • Éditeur de code SQL : sur MySQL, PostgreSQL et Oracle les suggestions de schémas, tables et colonnes arrivaient vides. Elles sont désormais complètes.
  • Cache des données : avec cacheDataMinutes actif, le nombre de lignes en cache n'expirait jamais, et une entrée expirée n'était plus remise en cache. Lignes et comptages expirent désormais après le délai configuré.
  • Pivot : enregistrer une seconde fois la même configuration pivot répondait 500.
  • Regroupement (SQL Server) : un regroupement côté serveur sans agrégats répondait 500.
  • Installeur Windows (IIS) : dans certains cas l'application démarrait avant que le site soit configuré et restait en erreur jusqu'au recyclage du pool. L'installeur recycle désormais le pool avant de démarrer le site.

📦 Paquets mis à jour

Paquet De À
WuicCore 1.7.14 1.7.15
Wuic.Webcore 1.7.14 1.7.15
WuicOData 1.7.14 1.7.15
RuntimeEfCore 1.7.14 1.7.15
Wuic.MySqlProvider 1.7.14 1.7.15
Wuic.PostgresProvider 1.7.14 1.7.15
Wuic.OracleProvider 1.7.14 1.7.15
wuic-framework-lib (npm) 1.7.14 1.7.15

🔧 Mises à jour opérationnelles recommandées

  1. SQL Server, export sans blocage : exécuter une fois ALTER DATABASE [<base de données>] SET ALLOW_SNAPSHOT_ISOLATION ON. L'option augmente l'utilisation de tempdb tant que des transactions sont ouvertes.
  2. Imports volumineux sur des tables à clé MAX très utilisées : mettre la clé dans le fichier, ou passer la table en IDENTITY/SEQUENCE, pour ne pas garder le verrou pendant tout l'import.
  3. Page « Traductions des données » sur les installations MySQL, PostgreSQL et Oracle existantes : dans les métadonnées des tables, la route _record_field_translations doit utiliser la connexion DataSQLConnection et ne pas être une route système. Les nouvelles installations sont déjà ainsi.
  4. Oracle : mettre à jour, ne serait-ce que pour la déconnexion.

v1.7.14

Retour à l'index

Version précédente publiée : 1.7.13 (24 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Cette version est issue d'un test de charge avec de nombreux utilisateurs simultanés sur une installation publique : export et import du même fichier, filtres, tris, rapports. L'export est quatre fois plus rapide et passe par une file d'attente qui protège le serveur ; l'import relit correctement les fichiers produits par l'export, y compris avec des lookups résolus à partir d'une description répétée. Deux défauts des grilles avec lookups et colonnes géographiques sont également corrigés.


📤 Export

  • Plus rapide et plus léger. Un export XLSX de 230 000 lignes passe de 28,5 s à 7,4 s et de 12,2 Go à 2,3 Go de mémoire allouée. Le contenu du fichier ne change pas.
  • File d'attente des exports. Le serveur exécute au plus maxConcurrentExports exports à la fois (par défaut : la moitié des cœurs, au moins 1). Les autres attendent dans l'ordre d'arrivée, jusqu'à maxQueuedExports (par défaut 10). Au-delà, la requête répond 503 errors.metaservice.export.queue_full.
  • Attente visible. Tant que l'export est en file d'attente, la boîte de dialogue de progression et la cloche des notifications affichent « En file d'attente : position N ». Un export en attente peut être annulé.
  • Paramètres à effet immédiat. Les deux clés sont dans l'éditeur des paramètres (section App Runtime) et sont lues à chaque export, sans redémarrage.
  • Nom de fichier unique. Deux exports de la même route lancés dans la même seconde n'écrivent plus le même fichier (auparavant tous sauf un répondaient 500).

📥 Import

Colonnes lookup dans le fichier : fkey_mode. Une route importable choisit comment ses colonnes lookup apparaissent dans le fichier, avec import.fkey_mode dans le props bag de la route :

  • description (par défaut) : la description, comme dans la grille ;
  • key : la valeur de la clé ;
  • both : les deux, la description sous le titre de la colonne et la clé sous le nom physique.

La boîte de dialogue d'import affiche le choix présélectionné et permet de le modifier pour un seul import. L'export suit le même choix, donc un fichier exporté se réimporte tel quel. use_descriptive_fkey reste accepté pour les clients qui ne connaissent pas fkey_mode.

En-têtes. Chaque colonne a son titre comme en-tête. Ce n'est que lorsque deux colonnes du même fichier ont le même titre que le nom physique de la colonne apparaît entre parenthèses.

Règles pour les lookups lus à partir de la description.

  • Description unique : sa clé est utilisée.
  • Description partagée par plusieurs enregistrements : en mise à jour, l'enregistrement conserve sa clé actuelle si elle fait partie des clés possibles ; sinon la ligne est rejetée avec la liste des clés candidates.
  • Clé et description dans le même fichier qui ne correspondent pas : la ligne est rejetée.

Autres corrections.

  • Les cellules date d'Excel sont lues comme des dates : un fichier exporté puis réimporté sans modification n'est plus rejeté.
  • Une clé primaire qui est aussi un lookup est résolue avant le contrôle d'existence de l'enregistrement.
  • Le contrôle d'existence utilise des paramètres SQL au lieu de concaténer les valeurs du fichier.

🐛 Corrections notables

  • Deux lookups vers la même table : la seconde colonne affichait une description vide. Chaque clé étrangère a désormais son propre alias dans la requête, sur toutes les bases de données.
  • Colonnes géographiques : trier la grille sur une colonne geography échouait sur SQL Server (erreur 249). Dans les scripts de premier démarrage, les colonnes géographiques ont mc_disable_sorting activé, la grille ne propose donc pas le tri.
  • Langues disponibles : GetSupportedLanguages renvoie les langues de la table lingue.
  • Rapports : reportQueryTimeout est facultatif, avec 120 secondes s'il manque ; la clé figure dans les appsettings.json des paquets.
  • Scripts de premier démarrage : sequences et identities démarrent après les données chargées, la première insertion n'entre donc pas en conflit avec une clé existante. Dans le tutoriel, Countries, DeliveryMethods, People, StateProvinces, Customers et Invoices génèrent la clé elles-mêmes au lieu de la demander dans le formulaire.
  • Oracle : les identities sont réalignées au démarrage.

📦 Paquets mis à jour

Paquet De À
WuicCore 1.7.13 1.7.14
Wuic.Webcore 1.7.13 1.7.14
WuicOData 1.7.13 1.7.14
RuntimeEfCore 1.7.13 1.7.14
Wuic.MySqlProvider 1.7.13 1.7.14
Wuic.PostgresProvider 1.7.13 1.7.14
Wuic.OracleProvider 1.7.13 1.7.14
wuic-framework-lib (npm) 1.7.13 1.7.14

🔧 Mises à jour opérationnelles recommandées lors de la mise à niveau

  1. Dimensionner la file d'attente des exports : chaque export complet d'une grande table utilise environ un cœur et 300 Mo pendant l'écriture. Sur un serveur partagé avec d'autres applications, régler maxConcurrentExports sous la valeur par défaut (par exemple 2).
  2. Routes importables : si vos fichiers contiennent des clés et non des descriptions, définir "import": { "fkey_mode": "key" } dans le props bag de la route ; avec both, l'export produit aussi les colonnes clés.
  3. Installations avec le tutoriel déjà chargé : les scripts de premier démarrage ne valent que pour les nouvelles installations. Pour retirer le tri des colonnes géographiques existantes, exécuter sur la base des métadonnées UPDATE _metadati__colonne SET mcdisablesorting = 1 WHERE LOWER(mc_db_column_type) IN ('point', 'geography', 'geometry') puis vider le cache des métadonnées.
  4. Clients qui lisent la progression depuis le WebSocket des notifications : le message de progression de l'export contient le nouveau champ queuePosition, présent tant que l'export attend dans la file.

v1.7.13

Retour à l'index

Version precedente publiee : 1.7.12 (20 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Cette version est avant tout une version de securite. Un audit de toute la surface des API a trouve des methodes et des controleurs accessibles sans connexion, ou par un utilisateur sans droits d'administration, et des donnees de session prises depuis la requete au lieu du serveur. Tous ont ete fermes, avec un test automatique pour chaque cas. S'y ajoutent les corrections issues des cellules de test sur PostgreSQL, MySQL et Oracle, et l'achevement du support multi-tenant.

La mise a jour est recommandee pour toutes les installations. Lisez la section finale « Mises a jour operationnelles recommandees » : quelques comportements changent.


🛡️ Securite

Appels AsmxProxy fermes par defaut. Chaque methode accessible depuis /api/Meta/AsmxProxy/{service}.{methode} exige desormais une session valide, sauf celles declarees anonymes. Trois attributs de l'espace de noms WEB_UI_CRAFTER.Helpers regissent l'acces :

  • [AsmxAnonymous] : methode appelable sans connexion (login, me, traductions, inscription, reinitialisation du mot de passe) ;
  • [AsmxAdmin] : reserve aux administrateurs (role superadmin) ;
  • [AsmxFirstRun] : anonyme seulement pendant le premier demarrage, puis reserve aux administrateurs.

Le proxy n'invoque en outre que les classes de service (MetaService, scaffolding, les services de l'application dans WEB_UI_CRAFTER.ProjectData.Servizi) : un nom de classe complet d'un autre espace de noms est refuse.

Session verifiee partout. Hardening best-effort sur toute la gestion de la session :

  • le cookie k-user est valide sur le serveur egalement avec les fournisseurs PostgreSQL et Oracle (jeton, expiration, session remplacee par une nouvelle connexion) ;
  • l'utilisateur des parametres personnels, du menu et du pivot est celui de la session, pas celui indique dans la requete ;
  • la deconnexion ne ferme que sa propre session ;
  • en multi-tenant, l'indicateur superadmin du cookie ne vaut que si la base de donnees le confirme ;
  • la liste des utilisateurs ne renvoie plus les jetons ni les IP de session.

Les points d'entree des controleurs sont eux aussi alignes :

  • l'editeur de appsettings.json, OData, l'upload et le rapport verifient la session et le role sur le serveur ;
  • l'upload reste dans le dossier de l'enregistrement ;
  • le designer n'accepte que les feuilles .css du projet ;
  • les fonctions d'administration des webhooks, des metriques et de la licence sont reservees aux administrateurs.

Notifications. Les points d'entree REST et WebSocket des notifications sont lies a l'utilisateur de la session : une requete pour un autre utilisateur recoit 403 errors.auth.notification_forbidden. Le WebSocket fonctionne aussi derriere un reverse proxy, grace a X-Forwarded-For.

Inscription desactivee par defaut. Elle ne s'active qu'avec registrationEnabled=true dans appsettings.json et n'attribue jamais un role admin ou superadmin : default-role-id doit indiquer un role existant sans droits d'administration.

Premier demarrage.

  • Le mot de passe choisi dans l'assistant pour l'administrateur est applique meme si le nom correspond a un utilisateur deja present.
  • Les scripts de premier demarrage MySQL et Oracle ne contiennent plus les utilisateurs des tests automatiques.
  • L'utilisateur dedie wuic_assistant (WUIC Assistant, serveur MCP) est cree avec un mot de passe genere pour chaque installation, enregistre dans scripts/mcp/wuic-assistant.credentials.json (exclu de git).

🤖 RAG et WUIC Assistant

  • /api/Rag/Chat exige une connexion ; /api/Rag/Query reste sans connexion.
  • Les details de /api/Rag/MetadataDetail qui renvoient des donnees (sample_records, lookup_value, db_*) sont reserves aux administrateurs.
  • La cle LLM configuree sur le serveur n'est jamais envoyee a un fournisseur ou une adresse choisis par l'appelant.
  • Le serveur MCP wuic-rag ouvre lui-meme la session en cas de besoin, avec WUIC_USER/WUIC_PASSWORD ou avec le fichier d'identifiants de l'utilisateur wuic_assistant.

🏢 Multi-tenant

  • Caches separes par tenant pour le menu, les permissions de table et de colonne, les styles, les routes disponibles et le cache de donnees : un tenant ne voit plus les entrees d'un autre.
  • La propagation d'une table aux tenants invalide le cache de chaque tenant de destination, si bien que la nouvelle entree apparait immediatement dans les menus.
  • Notifications par tenant.
  • Support de PostgreSQL.

🗄️ Fournisseurs de base de donnees

  • PostgreSQL : pagination, cache de donnees, filtres many-to-many vides, themes, dates avec n'importe quel hote.
  • MySQL : comptages sur les select distinct, contraintes systeme, chargement des fournisseurs sous Linux.
  • Oracle :
    • pagination, filtres geographiques (zone et distance), restriction des enregistrements par utilisateur et role, noms des procedures stockees, booleens sur des colonnes numeriques, regroupement sur du texte long, cache de donnees ;
    • traductions beaucoup plus rapides : de 3-4,6 s a 0,3-0,7 s ;
    • nombre correct de lignes mises a jour et supprimees ;
    • donnees geographiques completes dans les scripts de premier demarrage (tous les etats et pays) ;
    • demo du workflow d'approbation des commandes ;
    • noms des colonnes de la timeline alignes sur les autres bases de donnees.
  • Toutes : erreur de concurrence optimiste typee (409 errors.validation.optimistic_concurrency), chemin d'upload unique, dates de creation des notifications en UTC (migration automatique), restrictions par role correctes pour les utilisateurs ayant plusieurs roles.

🐛 Corrections notables

  • Navigation entre enregistrements via l'URL : en passant d'un enregistrement a l'autre en edition ou en detail, la boite de dialogue recharge le nouvel enregistrement au lieu d'afficher le precedent.
  • data-record-loaded revient a false quand la boite de dialogue recharge l'enregistrement, pour que les tests automatiques ne lisent pas d'anciennes donnees.
  • Filtre geographique attend le chargement de Google Maps avant de dessiner.
  • Liste du scheduler applique le modele avant de recharger les donnees.

📦 Paquets mis a jour

Paquet De À
WuicCore 1.7.12 1.7.13
Wuic.Webcore 1.7.12 1.7.13
WuicOData 1.7.12 1.7.13
RuntimeEfCore 1.7.12 1.7.13
Wuic.MySqlProvider 1.7.12 1.7.13
Wuic.PostgresProvider 1.7.12 1.7.13
Wuic.OracleProvider 1.7.12 1.7.13
wuic-framework-lib (npm) 1.7.12 1.7.13

🔧 Mises a jour operationnelles recommandees

  1. Services personnalises appeles avant le login : les methodes de vos services dans WEB_UI_CRAFTER.ProjectData.Servizi qui doivent repondre sans session doivent etre marquees [AsmxAnonymous] ; sans cela, elles repondent 401 errors.auth.unauthenticated.
  2. Inscription : si vous l'utilisez, definissez registrationEnabled=true et verifiez que default-role-id indique un role sans droits d'administration.
  3. Utilisateur wuic_assistant sur les installations existantes : l'ancien mot de passe par defaut n'est plus accepte. Definissez-en un nouveau depuis un administrateur et ecrivez-le dans scripts/mcp/wuic-assistant.credentials.json (ou dans les parametres de l'extension WUIC Assistant).
  4. Installations Oracle et MySQL avec des tutoriels jusqu'a la 1.7.12 : verifiez la table des utilisateurs et supprimez les utilisateurs wuic_e2e_admin, wuic_e2e_admin_2, wuic_e2e_admin_3 et guest_1, s'ils sont presents.
  5. Outils qui lisaient des donnees depuis /api/Rag/MetadataDetail ou utilisaient /api/Rag/Chat sans login : ils doivent desormais s'authentifier (pour les donnees, avec un administrateur).

v1.7.12

Retour à l'index

Version precedente publiee : 1.7.11 (20 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Cette version ferme pour de bon les rapports qui imprimaient une page vide sur MySQL et PostgreSQL. Les deux versions precedentes declaraient ce defaut corrige en agissant sur la requete : la requete n'etait pas le probleme, et le rapport continuait a sortir avec son en-tete et pas une seule ligne. La vraie cause a ete trouvee en comparant, sur la meme installation, un rapport livre dans le paquet et un rapport construit sur le champ a partir des colonnes de cette installation : les deux imprimaient blanc, donc le probleme n'etait pas dans le fichier du rapport.


📊 Les rapports impriment leurs donnees sur MySQL et PostgreSQL

Un rapport Stimulsoft garde dans son dictionnaire deux choses distinctes : la connexion a la base et le type de la source de donnees. A l'ouverture d'un rapport, le framework remplacait la connexion par celle du moteur en cours — StiMySqlDatabase, StiPostgreSQLDatabase — mais laissait la source de donnees avec le type sous lequel elle avait ete creee, StiSqlSource, ce qui pour Stimulsoft signifie SQL Server.

Une source SQL Server posee sur une base MySQL ne leve aucune erreur : elle renvoie simplement un jeu de donnees vide. Le rapport etait dessine correctement — en-tete, cadre, « page 1 sur 1 » — et n'imprimait pas une ligne.

La conversion de la source vers le type du moteur existait deja dans le produit, mais pour Oracle uniquement, a deux endroits distincts (la visionneuse et le designer). Elle couvre desormais MySQL et PostgreSQL dans les deux. Si vous avez des rapports qui imprimaient blanc, il n'y a rien a regenerer : rouvrez-les.

🔑 Index des metadonnees sur MySQL

Sur les installations MySQL creees par le premier demarrage guide, la migration qui cree les index sur les chemins chauds des metadonnees echouait avec Fatal error encountered during command execution.

La raison est dans la chaine de connexion ecrite par l'assistant : sans Allow User Variables=True, le pilote MySQL lit chaque @nom present dans un script comme un parametre au lieu d'une variable du serveur. Les requetes normales du framework utilisent bien des parametres, elles fonctionnaient donc ; cette migration utilise des variables du serveur, et mourait. La cle est maintenant ajoutee a la connexion des metadonnees, aussi bien quand l'assistant la compose que quand le backend la reecrit.

🧩 Requete dynamique sur PostgreSQL

La passerelle PostgreSQL appelait la fonction qui construit les requetes dynamiques en lui passant 19 arguments, alors que le satellite PostgreSQL en accepte 15 : l'appel echouait toujours, avec MissingMethodException. Les arguments sont desormais les bons, et le message d'erreur de cette passerelle indique aussi combien d'arguments ont ete passes et combien de versions de la methode existent — parce que « methode introuvable », tout seul, envoie chercher une methode qui est pourtant bien la.

📦 Paquets mis a jour

Paquet De À
WuicCore 1.7.11 1.7.12
Wuic.Webcore 1.7.11 1.7.12
WuicOData 1.7.11 1.7.12
RuntimeEfCore 1.7.11 1.7.12
Wuic.MySqlProvider 1.7.11 1.7.12
Wuic.PostgresProvider 1.7.11 1.7.12
Wuic.OracleProvider 1.7.11 1.7.12
wuic-framework-lib (npm) 1.7.11 1.7.12

🔧 Mises a jour operationnelles recommandees

  1. Aucun changement de configuration n'est requis : les cles de appsettings.json ne changent pas.
  2. Si vous avez des rapports qui imprimaient vide sur MySQL ou PostgreSQL, rouvrez-les : il n'y a rien a regenerer.
  3. Sur les installations MySQL deja en service, si vous voulez que la migration des index aboutisse, ajoutez Allow User Variables=True a MetaDataSQLConnection dans appsettings.json. Les nouvelles installations la recoivent du premier demarrage guide. Sur MySQL l'impact est limite : deux des trois index sont deja couverts par la contrainte d'unicite de la route et par l'index qu'InnoDB cree de lui-meme pour les cles etrangeres.

v1.7.11

Retour à l'index

Version precedente publiee : 1.7.10 (19 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Cette version ferme deux defauts que la 1.7.10 declarait corriges et qui continuaient pourtant a se produire : les rapports scaffoldes qui impriment une page vide, et le scaffolding d'une table depuis l'interface qui repond par une erreur. Ils ont ete retrouves par la meme serie d'installations sur machines vierges qui avait produit la version precedente, refaite cette fois contre le produit publie pour verifier les correctifs. Ils concernent toujours ceux qui n'utilisent pas SQL Server.


📊 Les rapports scaffoldes impriment vraiment leurs donnees sur MySQL et PostgreSQL

La 1.7.10 introduisait la reecriture de la requete des rapports generes par le framework, parce que le .mrt qui voyage dans le paquet porte les identifiants du moteur sur lequel il a ete cree. Cette reecriture n'entrait cependant jamais en action : elle cherchait la table de metadonnees avec le nom de la base du dictionnaire — qui vaut toujours Connessione — au lieu du nom de la source de donnees, qui est la route. Ne trouvant aucune table portant ce nom, elle sortait en silence, ne reecrivait rien et ne laissait aucune trace, et le rapport continuait a imprimer la page avec son en-tete et pas une seule ligne.

La route est desormais lue au bon endroit, et chaque cas ou la reecriture ne peut pas avoir lieu — aucune table de ce nom, table sans colonnes — laisse une ligne dans le journal du backend. Un rapport vide sans explication est precisement ce qui rendait ce defaut difficile a voir.

Si vous avez des rapports generes qui imprimaient blanc sur MySQL ou PostgreSQL, il n'y a rien a regenerer : rouvrez-les.

🧱 Scaffolding d'une table depuis l'interface sur Oracle

Sur Oracle, generer une table depuis l'interface repondait HTTP 500 avec ORA-00001: unique constraint ... violated sur la table des menus, et la route n'etait pas creee.

C'est le meme defaut corrige pour PostgreSQL dans la version precedente, reste a decouvert sur Oracle. Le schema declare la cle du menu en GENERATED BY DEFAULT AS IDENTITY, mais le framework insere ses propres entrees systeme avec la cle calculee a la main : le generateur n'avance pas, et la premiere ligne qui s'appuie sur lui demande une cle deja prise. Le realignement du generateur couvre maintenant les deux moteurs.

📦 Paquets mis a jour

Paquet De À
WuicCore 1.7.10 1.7.11
Wuic.Webcore 1.7.10 1.7.11
WuicOData 1.7.10 1.7.11
RuntimeEfCore 1.7.10 1.7.11
Wuic.MySqlProvider 1.7.10 1.7.11
Wuic.PostgresProvider 1.7.10 1.7.11
Wuic.OracleProvider 1.7.10 1.7.11
wuic-framework-lib (npm) 1.7.10 1.7.11

🔧 Mises a jour operationnelles recommandees

  1. Aucun changement de configuration : les cles de appsettings.json ne changent pas.
  2. Si vous avez des rapports generes sur MySQL ou PostgreSQL qui imprimaient vide, rouvrez-les : la requete est reecrite au moment du rendu, il n'y a rien a regenerer.
  3. Sur Oracle, si le scaffolding d'une table depuis l'interface vous repondait par une erreur de cle dupliquee, reessayez : le generateur de cles du menu est realigne apres chaque insertion avec cle explicite.

v1.7.10

Retour à l'index

Version precedente publiee : 1.7.9 (18 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Cette version est nee d'une serie complete d'installations de bout en bout sur des machines vierges : seize combinaisons, les quatre paquets de distribution face aux quatre moteurs supportes, en partant a chaque fois du zip publie et en suivant la documentation comme le ferait quelqu'un qui installe pour la premiere fois. Presque tout ce qui en est ressorti concerne ceux qui n'utilisent pas SQL Server : des rapports qui imprimaient une page vide, un scaffolding qui echouait, des index qui ne naissaient jamais. Tous silencieux — aucun message a l'ecran, juste une fonction qui ne marchait pas.


📊 Les rapports impriment de nouveau leurs donnees sur MySQL et PostgreSQL

En ouvrant un rapport du tutoriel sur MySQL ou PostgreSQL, la visionneuse dessinait la page — en-tete, cadre, « page 1 sur 1 » — et n'imprimait pas une seule ligne. Le meme rapport fonctionnait sur SQL Server.

La raison : un rapport scaffolde par le framework porte en lui la requete qui l'alimente, et cette requete est ecrite avec les identifiants du moteur sur lequel il a ete genere. Or le fichier .mrt voyage dans le paquet et il est le meme pour les quatre moteurs : celui des tutoriels contient des identifiants non quotes en majuscules. Sur SQL Server cela passe, la comparaison y etant insensible a la casse ; sur PostgreSQL un identifiant non quote est replie en minuscules et ne retrouve plus les colonnes, que le tutoriel cree quotees en PascalCase.

Desormais, avant le rendu, les rapports generes par le framework — reconnaissables au marqueur qu'ils portent dans le SELECT — font regenerer leur requete a partir des metadonnees pour le moteur de l'installation courante, avec les bonnes regles de quotage. Les rapports ecrits a la main dans le designer ne sont pas touches : leur requete reste la votre.

🧱 Scaffolding d'une table depuis l'interface sur PostgreSQL

Sur PostgreSQL, scaffolder une table depuis l'interface repondait HTTP 500 avec une violation de cle etrangere sur _metadati__colonne, et la route generee restait vide.

Le vrai defaut etait en amont, et il etait double. La sequence identity de la table des menus prend du retard des que des lignes sont inserees avec la cle explicite — ce que le framework fait en ajoutant ses propres entrees systeme : a partir de la, la premiere insertion qui s'appuie sur la sequence demande une cle deja prise. Et quand la creation de l'entree de menu echouait, le code supprimait la ligne de metadonnees de la table qu'il venait d'inserer, laissant les colonnes sans leur parent : l'erreur qui arrivait a l'utilisateur parlait donc de cles etrangeres et d'une table qui n'y etait pour rien.

La sequence est maintenant realignee apres chaque insertion avec cle explicite, et un menu qui ne se cree pas n'emporte plus les metadonnees de la table : au pire l'entree de menu s'ajoute depuis le designer.

⚡ Les index des metadonnees naissent vraiment

Les migrations de schema qui creent les index sur les chemins chauds des metadonnees — nom de la route, colonnes par table, scheduler — n'etaient pas appliquees sur une installation neuve, pour deux raisons distinctes.

La premiere : au demarrage d'une application fraichement installee, les chaines de connexion ne sont pas encore la, donc les migrations echouaient ; et comme la tentative etait consideree consommee, elles n'etaient plus retentees dans le processus. Sur une installation neuve, ou personne ne redemarre le service juste apres, ces index ne naissaient jamais. La condition « base de donnees pas encore configuree » ne consomme plus la tentative, et les migrations tournent des que l'assistant de premier demarrage a ecrit les chaines de connexion.

La seconde, sur Oracle uniquement : le script des index citait les colonnes quotees en minuscules alors que le schema les cree en majuscules, d'ou un ORA-00904 et une migration arretee la.

L'effet pour l'utilisateur se voit sur les pages qui dependent de ces index : ouverture d'une liste depuis le menu, retour dans une liste deja visitee, premiere entree du menu Administration. Sans index, ces operations atteignaient des dizaines de secondes sur PostgreSQL.

🤖 L'assistant VS Code repond aux questions au lieu d'ecrire du code

En demandant a l'assistant « quelles colonnes a la route X ? » — meme en ajoutant « ne modifie pas les fichiers » — il scaffoldait un composant et repondait en decrivant ce qu'il avait ecrit. La question restait sans reponse et le projet etait modifie contre la consigne.

Une demande qui est une question, ou qui interdit explicitement les modifications, met desormais l'assistant en lecture seule : les outils qui touchent au projet sont refuses, et la reponse se construit avec les outils d'interrogation (colonnes et metadonnees de la route, recherche dans le code et la documentation).

🔧 Des installations plus tolerantes aux aleas passagers

  • Windows : quand winget repond qu'une autre installation est deja en cours — typiquement Windows Update juste apres le demarrage — l'installeur ne s'arrete plus sur « installez-le a la main » : il retente trois fois avec une attente croissante. Cette condition se libere d'elle-meme en quelques dizaines de secondes.
  • Linux, Oracle : le conteneur Oracle declare le listener pret alors que le premier demarrage applique encore le mot de passe de l'utilisateur system. L'installeur sortait en erreur sur ORA-01017 ; il attend maintenant que les identifiants deviennent valides, et s'ils ne le deviennent pas il le dit clairement au lieu de laisser l'erreur reapparaitre plus tard sous un autre visage.

📚 Documentation

  • Pattern « Framework component + Custom data » : une nouvelle section explique que sur Oracle, quand vous ouvrez vous-meme la connexion avec DataSQLConnection, il faut amener la session sur votre schema (ALTER SESSION SET CURRENT_SCHEMA) ou qualifier les tables — sinon la premiere requete repond ORA-00942 alors meme que la table existe. Les autres moteurs n'en ont pas besoin : la base est dans la chaine de connexion.
  • Getting started : la voie VS Code (fichier de workspace, demarrage par F5, lanceur Fullstack) est desormais dans le texte de la page et plus seulement dans un bloc de code.
  • FIRST_STEPS du paquet (anglais, francais, espagnol, allemand) : ajout de la section sur l'ouverture du projet dans VS Code et sur le script npm qui sert le frontend. Elle n'existait que dans la version italienne.
  • README du kit sources Linux : ajout de la section sur le renommage du projet, jusqu'ici documentee seulement pour Windows.

📦 Paquets mis a jour

Paquet De À
WuicCore 1.7.9 1.7.10
Wuic.Webcore 1.7.9 1.7.10
WuicOData 1.7.9 1.7.10
RuntimeEfCore 1.7.9 1.7.10
Wuic.MySqlProvider 1.7.9 1.7.10
Wuic.PostgresProvider 1.7.9 1.7.10
Wuic.OracleProvider 1.7.9 1.7.10
wuic-framework-lib (npm) 1.7.9 1.7.10

🔧 Mises a jour operationnelles recommandees

  1. Aucun changement de configuration : les cles de appsettings.json ne changent pas.
  2. Sur les installations PostgreSQL et Oracle deja en service, les index manquants sont crees au premier demarrage avec la 1.7.10 : ce demarrage peut durer quelques secondes de plus, une seule fois.
  3. Si vous avez des rapports scaffoldes sur MySQL, PostgreSQL ou Oracle qui imprimaient vide, rouvrez-les : rien a regenerer, la requete est reecrite au moment du rendu.
  4. Si l'un de vos controleurs ouvre ses propres connexions sur Oracle, verifiez qu'il amene la session sur le schema des donnees ou qu'il qualifie les tables : voir la note dans la page des patterns.

v1.7.9

Retour à l'index

Version precedente publiee : 1.7.8 (18 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Une version courte et ciblee : l'indicateur de chargement mentait. Sur une route lente, la page restait vide pendant toute la duree de la requete, et ce qui finissait par apparaitre avait deja eteint l'indicateur a mi-parcours. Qui essayait le produit sur une grande table voyait un ecran blanc et en concluait que tout etait bloque.


⏳ La grille apparait tout de suite, et l'attente se voit

Le defaut avait deux moities, et chacune cachait l'autre.

La grille n'existait pas encore. Le tableau — et avec lui la surcouche de chargement, qui lui appartient — n'etait construit qu'a l'arrivee des donnees : le composant recevait les metadonnees en meme temps que le resultat de la requete, pas avant. Sur une route lente, cela signifiait aucun en-tete, aucune barre de commandes, aucun signe d'activite : juste le titre de la page, pendant toutes les secondes de la requete. Les metadonnees sont desormais publiees avant le lancement de la lecture des donnees : la grille se monte vide et l'indicateur tourne pendant toute l'attente. Mesure sur une route qui repond en 4 secondes : le tableau est a l'ecran apres 330 ms au lieu de 4 300.

L'indicateur s'eteignait a mi-chemin. Chaque appel au serveur allumait et eteignait l'etat « occupe » sans compter le nombre d'operations en cours. En ouvrant une route avec des colonnes lookup, le framework lance une douzaine de lectures de metadonnees en parallele de la requete de donnees : la premiere a repondre — au bout d'une demi-seconde — eteignait l'indicateur pour tout le monde, alors que la vraie requete continuait trois secondes de plus.

Les operations en vol sont maintenant comptees, et l'etat ne redevient libre qu'a la fin de la derniere. Sur la meme route, l'indicateur couvre toute l'attente au lieu de 600 millisecondes.

La correction a ete verifiee sur tous les archetypes — list, map, scheduler, chart, carousel, kanban, timeline, tree, spreadsheet — en mesurant pour chacun le moment ou l'indicateur s'allume, celui ou il s'eteint et celui ou les donnees apparaissent : dans aucun il ne s'eteint avant les donnees.

Un effet a connaitre : sur les routes comportant beaucoup de colonnes lookup, l'indicateur reste desormais allume quelques secondes apres que les lignes sont lisibles, parce que ces lectures de metadonnees se poursuivent reellement. Avant il disparaissait plus tot, mais en mentant.

🧩 Le suggereur du props bag active vraiment le drapeau

Dans le panneau Suggerer md_props_bag de l'editeur de metadonnees, cocher une entree booleenne — par exemple archetypes.list.advancedFilter, celle qui remplace les filtres de colonne par la barre de filtres — inserait dans le JSON "advancedFilter": false. La coche creait la cle mais y copiait la valeur d'exemple, qui pour ces drapeaux vaut false : il fallait s'en apercevoir et corriger a la main.

Une entree booleenne cochee entre desormais a true. Qui ne veut pas le drapeau ne le coche tout simplement pas : la valeur par defaut a l'execution est deja false. Les entrees non booleennes continuent de porter la valeur d'exemple, qui sert la de canevas a completer. Cela vaut pour les deux suggereurs, celui de la table et celui de la colonne.

📦 Paquets mis a jour

Paquet De A
WuicCore 1.7.8 1.7.9
Wuic.Webcore 1.7.8 1.7.9
WuicOData 1.7.8 1.7.9
RuntimeEfCore 1.7.8 1.7.9
Wuic.MySqlProvider 1.7.8 1.7.9
Wuic.PostgresProvider 1.7.8 1.7.9
Wuic.OracleProvider 1.7.8 1.7.9
wuic-framework-lib (npm) 1.7.8 1.7.9

🔧 Mises a jour operationnelles recommandees

  1. Aucune modification de configuration : les cles de appsettings.json ne changent pas.
  2. Une fois la bibliotheque npm mise a jour, reconstruire le frontend : les deux corrections vivent dans les composants, pas dans les metadonnees.
  3. Si votre application lit l'etat « occupe » du framework pour piloter sa propre interface, verifiez-la : cet etat reste maintenant actif jusqu'a la fin de la derniere operation en vol, donc il dure plus longtemps qu'avant. C'est le comportement correct, mais c'est un changement observable.
  4. Si une partie de votre code eteignait l'etat « occupe » en y ecrivant directement, passez aux methodes beginBusy / endBusy du toolbox, ou a resetBusy s'il s'agit d'un chemin de recuperation apres erreur : une ecriture directe eteint l'indicateur y compris pour les operations des autres.

v1.7.8

Retour à l'index

Version precedente publiee : 1.7.7 (17 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Une version nee de l'usage du produit plutot que de sa lecture : un geste qui manquait dans les listes, un exemple present sur trois bases de donnees sur quatre, des textes restes en italien sur des installations qui ne l'etaient pas, et des pages de documentation decrivant des ecrans differents des vrais.


🖱️ Double-clic sur une ligne : le formulaire de modification s'ouvre

Jusqu'a hier, le formulaire de modification d'un enregistrement ne s'ouvrait que depuis l'entree Modifier du menu d'actions de la ligne. Desormais un double-clic sur la ligne l'ouvre aussi.

Ce n'est pas un raccourci parallele qui reecrirait la meme logique : le framework remonte de la ligne cliquee jusqu'a son menu d'actions et execute cette meme commande. Les memes permissions s'appliquent (md_editable), ainsi que la regle conditionnelle evaluee sur cet enregistrement (md_conditional_update_rule) : la ou le crayon est absent ou desactive, le double-clic ne fait rien. C'est une garantie structurelle, pas une promesse : si demain les regles de qui peut modifier changent, elles changent pour les deux a la fois.

Le geste est ignore quand il vise autre chose : double-clic sur un bouton, un lien ou un champ de saisie (vous utilisez ce controle, ou vous selectionnez du texte), ou ligne deja ouverte en edition en ligne.

Cela vaut aussi pour la mise en page mobile en cartes, ou la liste reconnait deux touchers rapproches sur la meme carte. C'etait necessaire parce que, lorsque le geste provient d'un toucher, le navigateur ne delivre pas toujours l'evenement de double-clic : deux taps restent deux clics distincts.

🗓️ Le tutoriel SQL Server a enfin la page Timeline / Gantt

La documentation decrit l'archetype timeline/gantt et la base du tutoriel embarque deja les donnees d'exemple, mais sur SQL Server la route et l'entree de menu qui les ouvrent manquaient : elles n'existaient que sur MySQL, PostgreSQL et Oracle. Qui installait le tutoriel sur le moteur par defaut n'avait aucun moyen de voir cette vue, et la page de documentation restait invarifiable.

Le tutoriel SQL Server propose maintenant Exemples → Timeline (Gantt) : neuf taches sur deux projets, avec dependances entre taches, jalons, avancement et regroupement par projet. C'est un exemple complet et fonctionnel de md_props_bag.archetypes.timeline dont copier la configuration, y compris les deux points le plus souvent rates : les predecesseurs sur une colonne multiselect adossee a une table de liaison auto-referencante, et le regroupement sur un lookup plutot que sur du texte libre.

🌍 Des textes restes en italien

  • Chatbot RAG. Pendant le demarrage du moteur, le chat repond qu'il n'est pas encore pret. Ce message etait ecrit a la main en italien dans le code et arrivait tel quel sur une installation anglaise, francaise, espagnole ou allemande. C'est desormais une cle traduite en cinq langues. Il ne parle plus non plus de « telechargement des modeles » : depuis que l'installation les prerecupere, l'attente est le chargement en memoire, pas le telechargement — le message decrivait quelque chose qui n'avait pas lieu.
  • Workflow designer. Six commandes du menu (Rouvrir, Nouveau graphe, Enregistrer le graphe, Supprimer, Re-agencement automatique, Ouvrir le runner dans un nouvel onglet) etaient des litteraux italiens dans le code : sur une installation dans une autre langue, le menu sortait a moitie traduit.
  • L'avertissement de la carte sans cle Google. Il existait en deux langues et uniquement dans les paquets SQL Server ; sur les autres moteurs, la cle brute s'affichait a la place du message. Ce sont maintenant cinq langues sur les quatre moteurs.

🧹 Un tutoriel plus propre

Les vingt entrees Cline Prompt Tests disparaissent du menu du tutoriel : des restes d'essais internes qui n'avaient aucune raison de figurer dans une base d'exemple.

📚 Documentation

Les pages ci-dessous decrivaient le produit de maniere inexacte. Ce ne sont pas des retouches de forme : c'etaient des instructions qui menaient au mauvais endroit.

  • Premier demarrage. Le wizard n'etait pas decrit du tout. Le guide de demarrage explique desormais les deux modes d'installation (Base existante et Tutorial WideWorldImporters, le second present uniquement si le paquet embarque le tutoriel), le champ DataSQLConnection et le bouton de test dont tout le reste depend — tant que vous ne l'avez pas presse, la liste des bases reste desactivee —, l'utilisateur administrateur initial, et la duree du provisionnement : 30 s – 2 min en mode tutoriel, 1–4 min sur une base existante avec la generation automatique activee.
  • Il n'y a pas de mot de passe par defaut. La meme page annoncait admin / admin comme identifiants apres le premier demarrage. C'est faux : le mot de passe est celui choisi dans le wizard, et il n'y en a pas d'autre.
  • Licence. La procedure demandait d'ecrire les valeurs dans le fichier de configuration et de redemarrer le backend, sans jamais mentionner que l'interface existe. En collant la licence depuis Administration → Editeur AppSettings, section License, le backend recharge lui-meme la validation et la licence s'applique des la requete suivante. Le redemarrage n'est necessaire que dans l'autre cas, quand les valeurs sont ecrites a la main dans le fichier.
  • Scaffolding initial. La page ne disait pas que dans les paquets tutoriel il n'y a rien a scaffolder : la base de metadonnees arrive deja remplie, et la case qui enregistre les tables n'existe qu'en mode Base existante.
  • List Grid. Une nouvelle section liste les boutons que la toolbar affiche reellement a l'ouverture d'une route, et la condition de chacun. La page ne nommait que des commandes optionnelles ou transitoires — celles de la boite de progression d'import/export, qui n'existe que pendant un import ou un export — et aucune de celles que l'on voit des l'ouverture d'une liste.
  • Designer. La liste de la palette nommait cinq entrees, dont trois inexistantes sous ce nom, et ne disait rien des autres. On y trouve maintenant les trois groupes reels et les vrais noms des composants.
  • Mode Trial. Une installation sans licence limite chaque requete a 20 enregistrements : une liste qui affiche « 20 sur 20 » sur une table de plusieurs milliers de lignes tourne en Trial, elle n'est pas en panne. C'est desormais ecrit la ou c'est utile — page de telechargement et guide de demarrage — et plus seulement sur la page tarifs.

📦 Paquets mis a jour

Paquet De A
WuicCore 1.7.7 1.7.8
Wuic.Webcore 1.7.7 1.7.8
WuicOData 1.7.7 1.7.8
RuntimeEfCore 1.7.7 1.7.8
Wuic.MySqlProvider 1.7.7 1.7.8
Wuic.PostgresProvider 1.7.7 1.7.8
Wuic.OracleProvider 1.7.7 1.7.8
wuic-framework-lib (npm) 1.7.7 1.7.8

🔧 Mises a jour operationnelles recommandees

  1. Aucune modification de configuration : les cles de appsettings.json ne changent pas.
  2. Une fois la bibliotheque npm mise a jour, reconstruire le frontend : le double-clic vit dans le composant liste, pas dans les metadonnees.
  3. Si votre application avait deja un comportement lie au double-clic sur une ligne de liste, verifiez-le : le framework ouvre desormais le formulaire de modification sur ce meme geste.
  4. L'entree Timeline (Gantt) apparait dans les nouvelles installations tutoriel sur SQL Server. Une installation existante n'a pas a etre refaite : les donnees d'exemple sont deja la, seules manquent la route et l'entree de menu, que l'on peut ajouter depuis l'interface.

v1.7.7

Retour à l'index

Version précédente publiée : 1.7.6 (16 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Cette version corrige cinq défauts découverts en installant le framework sur des machines vierges, un pour chaque combinaison de système d'exploitation et de base de données. Le plus important concerne Oracle et PostgreSQL, où une page générée par le framework pouvait ne pas s'ouvrir selon la façon dont on écrivait son nom dans l'adresse. Les autres concernent Oracle XE et le paquet sources pour Linux.


🔤 Les routes s'ouvrent désormais quelle que soit la casse

Le nom d'une route naît en minuscules : une table Supplier devient la route supplier. Ouvrir /Supplier/List — c'est-à-dire écrire le nom de sa propre table — fonctionnait sur SQL Server et MySQL, où le moteur ignore la casse, mais pas sur Oracle ni PostgreSQL, qui répondaient Route 'Supplier' introuvable dans les métadonnées.

Même adresse, même scaffolding, un résultat différent selon la base sous-jacente. Sur Oracle l'effet se multipliait : la liste produite par le scaffolding initial, la page créée depuis l'interface, les composants qui montent un widget du framework et les API de métadonnées échouaient tous pour la même raison, et ressemblaient à quatre pannes distinctes.

La résolution d'une route se replie maintenant sur une comparaison insensible à la casse lorsque la comparaison exacte échoue : le chemin normal ne change pas, et les noms physiques des tables et des colonnes restent ceux écrits dans le schéma.

Si une installation contenait deux routes ne différant que par la casse, le framework ne peut pas en choisir une : il le dit désormais par un message explicite (HTTP 409, errors.metadata.route.ambiguous_case) qui énumère les routes en conflit, au lieu de répondre « introuvable ».

🗄️ Oracle XE : le scaffolding depuis l'interface

Générer une page à partir d'une table depuis le menu d'administration répondait 500 sur Oracle XE :

ORA-00932: inconsistent datatypes: expected NUMBER got BOOLEAN

Les colonnes de métadonnées qui représentent un interrupteur sont numériques, mais le provider y écrivait un booléen : un type qui, en SQL Oracle, n'existe qu'à partir de la 23ai. Sur 23ai la conversion implicite masquait le problème ; sur XE — l'édition la plus répandue — le serveur refusait l'insertion et le scaffolding s'arrêtait. Il écrit désormais 1 et 0, valables sur toutes les versions.

🐧 Paquet sources pour Linux

  • Le chatbot RAG était éteint. Le paquet déclarait le moteur .NET actif dans sa configuration mais ne le livrait pas : /api/Rag/Health répondait indéfiniment not-initialized, avec WuicRagEngine.dll introuvable. Le moteur est désormais présent ici aussi, comme il l'était déjà dans le paquet Windows.
  • Les modèles sont téléchargés pendant l'installation. À la première question, le chatbot devait récupérer 4,4 Go de modèles et d'index, et pendant plusieurs minutes il ne répondait que « initialisation en cours ». install.sh les récupère maintenant pendant l'installation, en parallèle du reste : la première question répond immédiatement. Le téléchargement se saute avec --skip-prefetch, ce qui rétablit le comportement précédent. Cette étape n'interrompt jamais l'installation : si le réseau ne suit pas, le chatbot les récupérera au premier usage.
  • Les fichiers pour les assistants de code n'étaient pas générés. Sous Linux le premier démarrage n'écrivait ni AGENTS.md, ni CLAUDE.md, ni .mcp.json, ni les skills : le modèle qui les produit n'était pas dans le paquet, et la génération était ignorée en silence. Ils sont maintenant livrés dans les deux paquets Linux.
  • Renommer le projet. rename-project.sh cherchait le projet uniquement dans son propre dossier et celui du dessus, alors que dans le paquet il se trouve un niveau plus bas : lancé comme documenté, il sortait avec WuicTest.csproj introuvable. Il cherche désormais aussi à cet endroit et, s'il ne trouve vraiment rien, il énumère les chemins essayés.
  • Le paquet ne transporte plus les restes de l'ancienne pile RAG Python (codebase_embeddings/, rag-setup.ps1, rag-start.ps1), remplacée par le moteur .NET en juin.

📦 Paquets mis à jour

Paquet De À
WuicCore 1.7.6 1.7.7
Wuic.Webcore 1.7.6 1.7.7
WuicOData 1.7.6 1.7.7
RuntimeEfCore 1.7.6 1.7.7
Wuic.MySqlProvider 1.7.6 1.7.7
Wuic.PostgresProvider 1.7.6 1.7.7
Wuic.OracleProvider 1.7.6 1.7.7
wuic-framework-lib (npm) 1.7.6 1.7.7

🔧 Mises à jour opérationnelles recommandées

  1. Sur Oracle et PostgreSQL : si vous aviez noté comme défaillantes des pages issues du scaffolding, réessayez-les après la mise à jour — c'était très probablement la cause.
  2. Sur Oracle XE : le scaffolding depuis l'interface est utilisable à partir de cette version ; les tables exposées auparavant n'ont pas à être refaites.
  3. Une installation depuis les sources sous Linux implique désormais 4,4 Go de téléchargement supplémentaire pendant l'installation, ou l'ajout de --skip-prefetch pour le reporter au premier usage du chatbot.
  4. Aucune modification de configuration n'est requise : les clés de appsettings.json ne changent pas.

v1.7.6

Retour à l'index

Version publiée précédente : 1.7.4 (16 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Cette version paraît le même jour que la 1.7.4 et corrige trois points découverts en refaisant l'installation sur des machines propres juste après sa publication. Le plus important concerne Oracle : le premier démarrage sur une base existante allait jusqu'au bout en annonçant la réussite, mais laissait l'application sans les tables de l'utilisateur. Les deux autres concernent le paquet Linux.


🗄️ Oracle : premier démarrage sur une base existante

Choisir le mode « base existante », indiquer son propre schéma et demander le scaffolding automatique menait à l'écran de connexion avec un menu sans aucune de ses tables, et sans message d'erreur. La raison n'était écrite que dans firstrun-scaffold-error.log, à côté de l'application :

firstRun scaffold failed for db='MONSCHEMA' dbms='oracle':
  ORA-01017: invalid credential or not authorized; logon denied

Sous Oracle, la « base de données » est le schéma, et le framework construisait la connexion en mettant comme utilisateur le schéma choisi tout en conservant le mot de passe saisi dans l'assistant, qui est celui de la personne qui configure : un identifiant que personne n'a tapé et qui n'existe généralement pas. Le scaffolding, qui réutilisait cette même connexion, n'arrivait pas à s'authentifier ; l'erreur atterrissait dans un bloc tolérant et l'assistant annonçait quand même la réussite.

La connexion conserve désormais l'utilisateur indiqué dans l'assistant — comme c'est déjà le cas sous PostgreSQL, où choisir la base ne change pas l'identité — et le schéma de travail est fixé sur la session par ALTER SESSION SET CURRENT_SCHEMA, la manière prévue par Oracle pour travailler dans un schéma sans en être l'utilisateur. Les installations où la personne qui configure est le schéma (toutes celles du tutoriel parmi elles) se comportent exactement comme avant.

Concrètement : de l'assistant au scaffolding puis à la connexion, les tables apparaissent dans le menu et les listes affichent les données.

🐧 Paquet Linux

  • Le chat RAG était éteint sur les quatre moteurs. Le moteur .NET s'installe correctement, mais les profils appsettings.linux.*.json ne contenaient aucune clé rag-* : le backend se rabattait sur un serveur Python que le paquet Linux ne distribue pas, et chaque requête répondait 503. Les clés sont maintenant dans les quatre profils.
  • Les modèles de rapport n'étaient pas distribués. Le dossier Reports/ n'arrivait pas dans le tarball, donc sous Linux aucune route ne proposait l'entrée Report. Il est désormais inclus.
  • Renommer le projet sous Linux. Le paquet de sources ne proposait qu'une seule façon de faire sien le template, et c'était un script PowerShell : sur une Ubuntu propre pwsh n'est pas là, l'installateur ne l'ajoute pas et les prérequis ne le demandent pas. À côté de rename-project.ps1 se trouve désormais rename-project.sh, qui fait les mêmes étapes — renommer .csproj, contrôleur et workspace VS Code, mettre à jour les contenus, aligner le nom dans package.json — avec --name, --in-place et --backend-port. Par défaut il clone dans un nouveau dossier et laisse l'original intact.
  • Le test de fumée recalait des installations saines. À la fin de l'installation, le script tentait une connexion administrative même lorsque l'application reste en premier démarrage — situation normale sous Oracle depuis la 1.7.4, où utilisateurs et métadonnées sont créés par l'assistant. L'installation se terminait par « Install completed but smoke tests failed » alors que tout allait bien. Le contrôle est désormais ignoré avec un avertissement qui explique comment le compléter.

🔧 Mises à jour opérationnelles recommandées

  1. Si vous avez téléchargé le tarball Linux de la 1.7.4 dans ses premières heures : téléchargez-le de nouveau. La première copie publiée contenait des assemblies de versions désalignées et le service ne démarrait pas (Could not load file or assembly 'WuicOData') ; la copie actuelle est correcte, et cette version la remplace de toute façon.
  2. Sous Oracle, une installation déjà terminée avec la 1.7.4 et restée sans tables dans le menu ne se répare pas toute seule : refaites le premier démarrage sur une base de métadonnées vide.
  3. Aucun changement de configuration n'est nécessaire : les clés de appsettings.json ne changent pas.

v1.7.4

Retour à l'index

Version publiée précédente : 1.7.3 (14 septembre 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Cette version concerne presque entièrement Oracle. Reprendre l'installation et le premier démarrage sur des machines propres — sous Windows avec IIS et sous Linux avec nginx — a fait apparaître quatre points où le parcours s'interrompait avant d'aboutir à une application fonctionnelle : le chargement des données du tutoriel, la création des utilisateurs, le chat RAG et, sous Linux, la génération même du mot de passe de la base de données. Aucun des quatre n'apparaît sur les autres moteurs.

Le reste, ce sont des corrections du premier démarrage valables pour tous les moteurs, plus deux sur le diagnostic des erreurs SQL.


🗄️ Oracle : données du tutoriel et premier démarrage

Le chargement des données initiales sous Oracle réussissait sur 472 instructions sur 18 141. Les autres échouaient avec ORA-01843: not a valid month, parce que les scripts de premier démarrage portent des dates et des nombres dans la convention italienne alors que la session Oracle utilisait les valeurs par défaut du serveur. L'exécution des scripts définit désormais NLS_DATE_LANGUAGE et NLS_NUMERIC_CHARACTERS avant la première instruction : 17 889 instructions sur 17 889, sous Windows comme sous Linux. Si vous avez essayé Oracle avec la 1.7.3 et trouvé les tables du tutoriel à moitié vides, c'est cela.

Toujours sur Oracle, trois corrections de l'installation Linux :

  • le mot de passe généré pour la base de données pouvait contenir le caractère @, qui casse la chaîne easy-connect de sqlplus : l'installation s'arrêtait avec ORA-12262 dans environ un cas sur trois, et le caractère fautif n'apparaissait dans aucun message ;
  • la création des bases du tutoriel et celle des utilisateurs d'authentification sont maintenant confiées à l'assistant de premier démarrage, qui est le chemin que toutes les autres plateformes suivaient déjà. Les scripts d'installation préparaient au contraire un schéma que l'assistant allait refaire de toute façon ;
  • appsettings.linux.oracle.json est livré avec firstRun actif, si bien que la première fenêtre du navigateur mène à l'assistant et non à une application sans métadonnées.

💬 Chat RAG sous Oracle

Le chat répondait 500 à la première question, avec ORA-00933: SQL command not properly ended. Les requêtes du chat se terminent par un point-virgule — correct dans SQL*Plus et sur les autres moteurs, mais pour le pilote Oracle il fait partie du texte de l'instruction. Le point-virgule final est désormais retiré avant l'exécution, sauf pour les blocs PL/SQL, où END; est légitime.

🚀 Premier démarrage (tous les moteurs)

  • L'assistant s'arrête avec un message si la base de données indiquée ne figure pas parmi celles lues sur le serveur. Auparavant il poursuivait : l'installation se terminait et le menu s'ouvrait, mais chaque grille restait vide parce que les métadonnées pointaient vers une base inexistante. Le message est traduit dans les 5 langues.
  • Sous Linux, appsettings.json dans le dossier de l'application est un lien symbolique vers /etc/wuiccore/appsettings.json. L'écriture atomique de la configuration résout désormais le lien avant d'écrire : sans cela, l'assistant écrivait un nouveau fichier à la place du lien, l'application continuait de lire l'ancien, et le premier démarrage ne se terminait jamais.
  • Les fichiers de configuration écrits par l'installateur restent accessibles en écriture au service (mode 0660, groupe du service). L'assistant échouait à l'enregistrement final sur une installation fraîchement créée.

🔎 Diagnostic des erreurs SQL

Le JSON envelope d'erreur que la boîte de dialogue montre à un administrateur affirmait deux choses fausses :

  • sqlProvider indiquait mssql pour toute erreur qui n'était pas MySQL — donc aussi pour les exceptions Oracle et PostgreSQL. La valeur dérive maintenant du type de l'exception, et les providers non reconnus déclarent unknown au lieu d'un nom erroné ;
  • query restait vide sur les chemins qui utilisent ADO.NET directement au lieu de la couche Dapper (dont le chat RAG), même avec le diagnostic actif. La capture de la commande couvre désormais les deux chemins, avec le même masquage des paramètres sensibles.

🐛 Corrections notables

  • Liste des modèles LLM sans clé d'API : l'endpoint contactait le fournisseur même sans clé configurée, et la page des paramètres attendait la réponse réseau. Sans clé, la liste locale sélectionnée est désormais renvoyée immédiatement.

🔧 Mises à jour opérationnelles recommandées

  1. Si vous utilisez Oracle, mettez à jour avant de refaire une installation : les corrections ci-dessus concernent le parcours de premier démarrage et n'ont pas d'effet rétroactif sur une base déjà à moitié peuplée. Sur une installation déjà abîmée, mieux vaut repartir d'une base vide.
  2. Sous Linux, vérifier après la mise à jour que appsettings.json dans le dossier de l'application est toujours le lien vers /etc/wuiccore/appsettings.json et non un fichier autonome laissé par un premier démarrage de la 1.7.3.
  3. Aucun changement de configuration n'est nécessaire : les clés de appsettings.json ne changent pas.

v1.7.3

Retour à l'index

Version précédente publiée : 1.7.0 (14 août 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


La nouveauté est l'installation en une seule commande sous Windows. Le reste, ce sont des corrections à l'installation et au premier démarrage, trouvées en rejouant toute la procédure sur des machines propres, sous Windows et sous Linux, avec SQL Server, MySQL et PostgreSQL. Deux d'entre elles empêchaient même d'atteindre l'assistant : sous Linux avec MySQL le chargement de la base s'arrêtait à la première instruction, et le scaffolding automatique de l'assistant ne générait pas les métadonnées, laissant l'application avec un menu vide.


💾 Installation en une commande sous Windows

Depuis une fenêtre PowerShell :

irm https://wuic-framework.com/install.ps1 | iex

Le script fait seul tout ce qui était auparavant une liste d'étapes manuelles : il vérifie le runtime ASP.NET Core 10 et l'installe s'il manque, cherche une instance SQL Server joignable et, s'il n'en trouve aucune, installe SQL Server 2022 Express, télécharge le dernier paquet publié, l'extrait et ouvre le navigateur sur l'assistant de premier démarrage. C'est le jumeau Windows de install.sh, et il fonctionne avec Windows PowerShell 5.1 : installer PowerShell 7 n'est donc pas nécessaire.

L'application est publiée dans IIS : le script active les fonctionnalités IIS manquantes, installe l'ASP.NET Core Hosting Bundle, crée le pool d'applications et le site sur le port choisi, et accorde à l'identité du pool les droits sur le dossier ainsi qu'un login sur SQL Server. Une élévation est nécessaire : le script la demande une seule fois, via l'invite Windows habituelle.

Avec -Kestrel, rien n'est touché dans IIS et l'application tourne dans une fenêtre de console, redémarrable avec start-wuic.cmd. C'est le bon choix lorsqu'on n'a pas les droits d'administrateur, lorsque IIS est désactivé par une politique d'entreprise, ou pour un essai jetable.

Les options les plus utilisées : -WithTutorial télécharge le paquet avec la base de démonstration WideWorldImporters, -Port change le port, -ListenAll écoute sur toutes les interfaces au lieu de localhost seulement, -SqlServer désigne une instance existante, -Dbms mysql|postgres installe et configure un moteur autre que SQL Server.

Un prérequis à connaître avant de choisir le paquet : la variante du tutoriel au format .bak contient une sauvegarde native SQL Server 2022 et exige donc SQL Server 2022 ou supérieur, car la restauration n'est pas rétrocompatible. Sous SQL Server 2019, il faut utiliser la variante avec les scripts SQL, prise en charge à partir de 2019 ; l'installateur le détecte de lui-même et choisit la bonne variante pour l'instance qu'il trouve.

Par rapport à la première version du script, trois choses que l'on rencontrait immédiatement ont été corrigées :

  • avec -Dbms mysql ou -Dbms postgres, l'installateur écrivait ses propres secrets dans le dossier d'installation puis refusait ce même dossier comme « non vide », en sortant avec le code 2 douze secondes après l'avoir rempli lui-même ; l'extraction supprimait en outre le mot de passe root fraîchement généré. Les fichiers de l'installateur ne comptent plus dans le contrôle et les secrets survivent à l'extraction ;
  • relancer la commande sur une machine où l'installation existait déjà ne mène plus à une impasse ;
  • avec -Dbms postgres, le tutoriel requiert l'extension PostGIS, qui sous Windows n'est pas posée avec PostgreSQL : le chargement mourait à mi-parcours avec extension "postgis" is not available, une erreur qui ressemblait à un défaut des scripts SQL. L'installateur vérifie désormais les extensions disponibles et, si elle manque, installe le bundle pour la version de PostgreSQL trouvée.

L'installateur dit maintenant ce qu'il fait y compris pendant les phases longues : l'installation de SQL Server Express et npm install peuvent rester des minutes sans afficher une ligne, et jusqu'ici la fenêtre semblait figée. Toutes les dix secondes de silence, il indique depuis combien de temps il travaille et quelle a été la dernière ligne utile.

🐧 Installation sous Linux

Trois corrections, toutes sur le chemin du premier démarrage.

Le framework ne démarrait pas sur les paquets obfusqués. La protection anti-tamper appliquée à la publication empêchait le démarrage sous Linux. Elle a été retirée : l'obfuscation des symboles reste, la protection qui bloquait l'exécution non.

Le chargement de la base MySQL s'arrêtait à la première instruction. Le script de bootstrap supposait une base déjà sélectionnée, alors que les dumps ne contiennent plus la directive USE, et le chargement mourait avec ERROR 1046 (3D000): No database selected. Ceux qui ont installé avec MySQL à partir du paquet précédent rencontrent toujours cette erreur : c'est la raison principale d'installer cette version.

Le profil de configuration n'était pas copié dans le projet. Le fichier appsettings.json livré dans le paquet des sources pointe vers une instance SQL Server nommée, qui n'existe pas sous Linux : en suivant la documentation, dotnet run mourait au bout de quarante-cinq secondes avec error: 26 - Error Locating Server/Instance Specified et l'assistant n'apparaissait jamais. Les clés dépendant du moteur sont désormais copiées automatiquement dans le projet.

Les versions d'Ubuntu réellement prises en charge sont documentées : 22.04 et 24.04 LTS. Sous 24.04, SQL Server nécessite un démarrage en compatibilité ; la 26.04 n'est pas prise en charge par Microsoft pour SQL Server.

🌍 Assistant de premier démarrage en cinq langues

L'assistant de premier démarrage ne parlait qu'italien, quel que soit le navigateur. Il se présente maintenant dans la langue du navigateur parmi les cinq gérées (italien, anglais, français, espagnol, allemand) et, en choisissant la langue de l'utilisateur administrateur, toute la page bascule immédiatement dans cette langue. Pour une langue non gérée, le repli est l'anglais.

Les messages produits par l'assistant pendant la configuration sont eux aussi traduits : résultat du test de connexion, erreurs de validation de la chaîne de connexion et confirmation de recréation de la base de métadonnées.

🐛 Corrections notables

  • Le scaffolding automatique de l'assistant ne générait pas les métadonnées. Au premier démarrage, la case « Exécuter le scaffolding automatique des tables de la BD sélectionnée » cochée, l'application démarrait avec un menu vide et aucune route : le scaffolding s'exécutait sur une connexion différente de celle qui venait d'être choisie dans l'assistant. Les connexions choisies dans l'assistant sont désormais réellement utilisées, et à la première connexion le menu contient les tables de son propre schéma.
  • Modification ou suppression sans clé : désormais refusées. Si la charge utile d'une mise à jour ou d'une suppression ne contenait aucune colonne reconnue par les métadonnées, la clause WHERE générée restait vide et l'instruction touchait toutes les lignes de la table, en renvoyant de surcroît un résultat positif. C'est le cas d'une clé primaire envoyée avec une casse différente de celle du schéma. L'opération est maintenant refusée avec HTTP 400 et le code errors.metaservice.crud.missing_key_predicate, et le message énumère les clés reçues pour que la cause soit immédiatement claire.
  • Sans clé Google Maps, l'application restait bloquée. L'absence de clé dans GoogleMaps:ApiKey produisait une erreur JavaScript qui remontait jusqu'à la boîte de dialogue d'erreur applicative et rendait toute l'interface inutilisable, pas seulement la carte. Le composant carte affiche désormais un avertissement discret dans sa propre vue et le reste de l'application continue de fonctionner.
  • Scene 3D dans le plan Professional. Les routes du visualiseur et du concepteur Scene 3D déclarent la fonctionnalité scene3d-designer comme requise, mais aucun plan ne l'incluait : sur toute installation Professional, le contrôle renvoyait vers la page d'accès refusé. La fonctionnalité fait maintenant partie du plan Professional.
  • Des scripts de premier démarrage plus petits de deux ordres de grandeur. Les scripts de premier démarrage contenaient les données des tables de journalisation, des conversations du chatbot et des contenus de tableaux de bord : journaux d'erreurs et discussions de développement expédiés dans chaque paquet. Ces tables ne voyagent plus qu'avec leur structure. Le script de métadonnées du premier démarrage passe de 468 Mo à 3,7 Mo dans le profil minimal et à 14 Mo dans celui du tutoriel (les données de démonstration WideWorldImporters restent à part et gardent leur taille).
  • Documentation du chatbot alignée sur le moteur réel. Les pages d'installation mentionnaient encore Python et un service séparé pour le chatbot RAG. Le moteur est natif .NET/ONNX et tourne dans le processus de l'application depuis la 1.3.0 : ni Python, ni installation séparée. La taille des modèles téléchargés au premier usage a également été corrigée — environ 4,5 Go.
  • Quatre pages de documentation vides (chatbot RAG, licences, listes de diffusion, tableaux croisés) ont été rédigées, dans les cinq langues.

🔧 Mises à jour opérationnelles recommandées

  1. Ceux qui ont installé avec MySQL sous Linux à partir du paquet précédent doivent réinstaller avec cette version : le chargement de la base était interrompu et l'installation n'était pas complète.
  2. Vérifier les intégrations qui écrivent via les API CRUD : un appel qui jusqu'ici mettait à jour toute la table sans s'en apercevoir reçoit désormais HTTP 400. Le message d'erreur énumère les clés reçues, et la correction consiste presque toujours à aligner le nom de la clé primaire sur la casse du schéma.
  3. En cas d'utilisation de Scene 3D avec une licence Professional émise avant cette version, demander une licence à jour : la fonctionnalité scene3d-designer doit être incluse dans le plan.
  4. Pour une nouvelle installation sous Windows, utiliser la commande en une étape plutôt que la procédure manuelle. Sur une instance SQL Server 2019, choisir la variante du tutoriel avec les scripts SQL.
  5. En cas d'utilisation du composant carte, configurer GoogleMaps:ApiKey dans appsettings.json : sans clé, la carte affiche un avertissement, mais le reste de l'application demeure utilisable.

v1.7.1

Retour à l'index

Version précédemment publiée : 1.7.0 (15 août 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Une version de consolidation avec un front nouveau — l'installation sous Windows en une commande — et une série de corrections nées de l'installation du produit à partir de zéro sur des machines propres, en suivant la documentation à la lettre. Plusieurs concernent Linux, où certaines choses ne fonctionnaient pas du tout : le chatbot manquait dans le paquet, les rapports ne s'ouvraient pas, et ceux qui partaient des sources ne parvenaient pas à démarrer l'application.


💾 Installation sous Windows en une commande

Depuis une fenêtre PowerShell :

irm https://wuic-framework.com/install.ps1 | iex

Le script fait tout seul ce qui était auparavant une liste d'étapes manuelles : il vérifie le runtime ASP.NET Core 10 et l'installe s'il manque, cherche une instance SQL Server accessible et, s'il n'en trouve aucune, installe SQL Server Express, télécharge le dernier paquet publié, l'extrait et ouvre le navigateur sur l'assistant de premier démarrage. C'est le jumeau Windows de install.sh, et il est compatible avec Windows PowerShell 5.1, donc il ne nécessite pas d'installer PowerShell 7.

L'application est publiée dans IIS : le script active les fonctionnalités IIS manquantes, installe l'ASP.NET Core Hosting Bundle, crée le pool d'applications et le site sur le port choisi, et accorde à l'identité du pool les permissions sur le dossier ainsi que la connexion SQL Server. Une élévation est nécessaire : le script la demande une seule fois, via l'invite Windows habituelle.

Avec -Kestrel, rien n'est touché dans IIS et l'application tourne dans une fenêtre de console, relançable avec start-wuic.cmd. C'est le bon choix lorsqu'on ne dispose pas des droits d'administrateur, lorsque IIS est désactivé par une stratégie d'entreprise, ou pour un essai jetable.

Les options les plus utilisées : -WithTutorial télécharge le paquet avec la base de démonstration WideWorldImporters, -Port change le port, -ListenAll écoute sur toutes les interfaces au lieu de localhost uniquement, -SqlServer désigne une instance existante, -Dbms choisit un moteur autre que SQL Server.

Un prérequis à connaître avant de choisir le paquet : la variante du tutoriel au format .bak contient une sauvegarde native SQL Server 2022 et exige donc SQL Server 2022 ou supérieur, car la restauration n'est pas rétrocompatible. Sous SQL Server 2019, il faut utiliser la variante avec les scripts SQL, prise en charge à partir de 2019 ; l'installeur s'en rend compte tout seul et choisit la variante adaptée à l'instance qu'il trouve.

Sous Windows Server, le moteur de base de données doit être installé au préalable. La commande se procure les composants manquants via winget, absent de Windows Server : sans instance déjà accessible, l'installation s'arrête et le signale. Cela vaut pour tous les moteurs, pas seulement SQL Server.

🐧 Linux : le paquet est enfin complet

Ceux qui installaient sous Linux trouvaient trois choses cassées, toutes corrigées dans cette version.

Le chatbot RAG était absent. Le moteur de recherche sémantique .NET/ONNX n'était inclus que dans les paquets Windows : chaque tarball Linux sortait sans lui, et GET /api/Rag/Health répondait 503 rag-server-unreachable indéfiniment. Le tarball le contient désormais, avec les bibliothèques natives linux-x64 complètes : sur une machine dotée de CUDA 12 et cuDNN 9, le GPU est utilisé sans intervention manuelle, sinon le moteur retombe sur le CPU.

Le moteur sémantique ne trouvait pas ses propres bibliothèques natives. Il les cherchait dans PATH, séparées par ;, ce qui est la convention Windows ; sous Linux, le chargeur utilise LD_LIBRARY_PATH et les deux-points.

Les rapports ne s'ouvraient pas. Le chemin du cache était construit avec les barres obliques inverses de Windows et une barre initiale, si bien que sous Linux il aboutissait à la racine du système de fichiers au lieu du dossier de l'application. La visionneuse renvoyait une erreur qui ressemblait à un problème de configuration.

Et pour ceux qui partent des sources : l'application ne démarrait pas du tout. Le paquet NuGet WuicCore embarquait une protection anti-altération dont le code d'initialisation n'est pas compatible avec le runtime .NET sous Linux, et qui échouait avant d'exécuter une seule ligne de l'application. Sous Windows, cette même bibliothèque démarrait sans problème, ce qui explique pourquoi le défaut est resté invisible si longtemps. La protection a été retirée ; le reste de l'obfuscation demeure inchangé.

📦 Kit sources : il compile sur une machine propre

Le paquet destiné aux développeurs traînait quelques hypothèses qui ne valaient que sur la machine où il était construit.

  • Le lock des dépendances voyage dans le paquet. Sans lui, npm install avec npm 10.9.x — la version livrée avec Node.js 22 LTS, c'est-à-dire celle que la documentation elle-même exige — s'interrompt lors de la résolution des dépendances peer. Le lock est désormais inclus, l'installation est reproductible et deux développeurs obtiennent le même arbre.
  • Les bibliothèques 3D sont déclarées. three, three-gpu-pathtracer, three-mesh-bvh et @dimforge/rapier3d-compat étaient importées sans figurer parmi les dépendances : sur la machine de développement du framework elles étaient présentes par d'autres voies, sur une machine propre la compilation s'arrêtait sur un import non résolu. Ce sont des dépendances peer optionnelles : ceux qui n'utilisent pas les scènes 3D ne les embarquent pas.
  • Les chemins des ressources Angular pointaient hors du paquet et la compilation échouait sur des fichiers inexistants.
  • L'espace de travail prêt pour les assistants LLM était généré sans ses propres réglages.

🌍 Assistant de premier démarrage

L'assistant ne parlait qu'italien, quel que soit le navigateur. Il se présente désormais dans la langue du navigateur parmi les cinq prises en charge (italien, anglais, français, espagnol, allemand) et, en choisissant la langue de l'utilisateur administrateur, toute la page bascule immédiatement dans cette langue. Pour une langue non prise en charge, le repli est l'anglais. Les messages produits pendant la configuration sont également traduits : résultat du test de connexion, erreurs de validation de la chaîne de connexion et confirmation de recréation de la base de métadonnées.

Le scaffolding d'une base existante est désormais actif par défaut. Ceux qui désignaient leur propre base et acceptaient les valeurs proposées obtenaient une application sans aucune route, ses tables ignorées. Le mode tutoriel n'est pas concerné.

🐛 Corrections notables

  • Modification ou suppression sans clé : désormais refusées. Si la payload d'une mise à jour ou d'une suppression ne contenait aucune colonne reconnue par les métadonnées, la clause WHERE générée était vide et l'instruction touchait toutes les lignes de la table, en renvoyant de surcroît un résultat positif. C'est le cas d'une clé primaire envoyée avec une casse différente de celle du schéma. L'opération est maintenant refusée avec HTTP 400 et le code errors.metaservice.crud.missing_key_predicate, et le message énumère les clés reçues pour rendre la cause immédiatement visible.
  • Cartes sans clé Google : un avertissement au lieu d'un blocage. Lorsque la Maps JavaScript API n'est pas chargée — généralement parce que la clé n'a pas été configurée — le composant affichait une boîte de dialogue modale qui figeait toute la page. Un encadré apparaît désormais à la place de la carte pour expliquer ce qui manque, et le reste de la page reste utilisable.
  • Réinstallation sur MySQL : fini l'impasse. Le mot de passe du moteur est généré par l'installeur lui-même ; en relançant la commande sur la même machine, il ne parvenait pas à le relire, sondait avec un mot de passe vide et concluait que la base ne répondait pas, alors qu'elle répondait parfaitement. La vérification de la version minimale a également été corrigée : elle ne s'exécutait jamais, car l'avertissement MySQL sur le mot de passe en ligne de commande se retrouvait dans la sortie analysée.
  • Scene 3D dans le plan Professional. Les routes de la visionneuse et du concepteur Scene 3D déclarent la fonction scene3d-designer comme requise, mais aucun plan ne l'incluait : sur toute installation Professional, le contrôle renvoyait vers la page d'accès refusé. La fonction fait désormais partie du plan Professional.
  • Les appsettings d'exemple ne contiennent plus de mot de passe réel.
  • Documentation du chatbot alignée sur le moteur réel. Les pages d'installation mentionnaient encore Python et un service séparé pour le chatbot RAG. Le moteur est natif .NET/ONNX et s'exécute dans le processus de l'application depuis la 1.3.0 : ni Python, ni installation à part. La taille des modèles téléchargés au premier usage a également été corrigée, elle est d'environ 4,5 Go.
  • Quatre pages de documentation vides (chatbot RAG, licences, listes de diffusion, tableaux croisés) ont été rédigées, dans les cinq langues.

📚 Prérequis corrigés dans la documentation

Les pages de démarrage annonçaient des exigences qui ne correspondaient pas à ce qui a été mesuré lors d'installations sur des machines propres :

  • Node.js 22 LTS, et non « 20 ou supérieur » : c'est la version avec laquelle le paquet est testé.
  • PowerShell 5.1 suffit. Les scripts inclus fonctionnent avec la PowerShell préinstallée sous Windows ; PowerShell 7 est recommandée, pas requise.
  • Sous Windows Server, la base de données doit être installée avant la commande d'installation.

📦 Paquets mis à jour

Paquet De À
WuicCore (NuGet) 1.7.0 1.7.1
wuic-framework-lib (npm) 1.7.0 1.7.1

🔧 Mises à jour opérationnelles recommandées pour ceux qui migrent

  1. Vérifier les intégrations qui écrivent via les API CRUD : un appel qui mettait jusqu'ici à jour toute la table sans s'en apercevoir reçoit désormais HTTP 400. Le message d'erreur énumère les clés reçues, et la correction consiste presque toujours à aligner le nom de la clé primaire sur la casse du schéma.
  2. Sous Linux, remplacer le paquet par celui de cette version même si l'application semble fonctionner : le chatbot RAG et la visionneuse de rapports n'étaient pas opérationnels dans les versions précédentes.
  3. Si vous utilisez Scene 3D avec une licence Professional émise avant cette version, demandez une licence à jour : la fonction scene3d-designer doit être incluse dans le plan.
  4. Ceux qui partent du kit sources peuvent exécuter npm install sans options supplémentaires : le lock inclus rend l'installation reproductible.
  5. Pour une nouvelle installation sous Windows, utiliser la commande en une étape plutôt que la procédure manuelle. Sur une instance SQL Server 2019, choisir la variante du tutoriel avec les scripts SQL ; sous Windows Server, installer d'abord le moteur de base de données.

v1.7.0

Retour à l'index

Version publiée précédente: 1.5.0 (21 juillet 2026)
Backend: .NET 10 + IIS / Linux nginx
Frontend: Angular 21


Paquets remplacés le 15 août 2026. Les archives publiées initialement contenaient un appsettings.json avec autoGeneratedQueryTimeout à 1 : avec cette valeur, toute requête dépassant une seconde se termine par une erreur du serveur. Quelques réglages d'en-tête (logo, orientation du menu, sélecteur de thèmes, notifications) étaient également restés d'une session de test. Les archives ont été reconstruites et leurs sommes de contrôle mises à jour.

Si vous avez téléchargé avant le 15 août : téléchargez à nouveau le paquet, ou ouvrez appsettings.json et remettez autoGeneratedQueryTimeout à 30, en supprimant les clés header-logo, header-logo-position, header-menu-orientation, header-show-theme-selector, header-menu-multicolumn-submenu et header-show-notifications si vous ne les avez pas définies vous-même. Aucun de ces réglages ne touche aux données : modifier le fichier et redémarrer suffit.


Trois semaines de travail sur deux fronts. Le premier est l'apparence : arrive le Theme Builder, une page depuis laquelle composer des thèmes sur mesure — couleurs, typographie, arrière-plan, densité, rendu de la grille — qui s'appliquent à tous les utilisateurs de l'installation, et l'en-tête de l'application a été redessiné et rendu configurable. Le second est l'intégration et l'observabilité : le nouveau Webhook Hub pour recevoir et envoyer des événements avec signature et réessais, et le Performance Inspector qui mesure les temps de fetch et de rendu par route. Le chatbot apprend à agir sur trois autres surfaces de l'application et à interroger le schéma de la base de données.


🎨 Theme Builder

Une nouvelle page sous Administration permet de composer des thèmes personnalisés sans toucher au code. Chaque thème enregistré apparaît dans le sélecteur de thèmes de tous les utilisateurs de l'installation, à côté de ceux fournis.

Ce que l'on peut régler :

  • Couleur principale, à partir de laquelle est générée l'échelle complète de 11 nuances : l'échelle reste cliquable, et choisir une nuance plus sombre la promeut en couleur principale. Une étiquette indique le rapport de contraste WCAG atteint (AAA / AA / AA-large / fail).
  • Surfaces claires et sombres, rayon des coins et densité (confortable ou compacte).
  • Typographie : famille de caractères issue d'un catalogue de polices système ou pile libre, et taille de base qui met à l'échelle toute l'interface.
  • Arrière-plan de page : couleur unie, dégradé ou image. Le dégradé peut avoir une dérive lente optionnelle qui fait osciller son inclinaison dans le temps ; l'image se configure avec ajustement, répétition, position et un voile sombre pour que le texte reste lisible.
  • Grille : les lignes alternées et la ligne sélectionnée ne sont plus des couleurs fixes mais des mélanges entre la surface et un accent, pilotés par deux molettes d'intensité, avec la possibilité d'un accent différent de la couleur principale.
  • Mode clair/sombre laissé libre ou imposé par le thème.

L'aperçu est en direct et applique le thème à toute la page pendant qu'on le compose, sans toucher aux préférences de l'utilisateur : en quittant, en rechargeant ou en fermant le navigateur, son propre thème revient.

L'export Excel suit le thème : un fichier exporté avec un thème personnalisé actif sort avec les couleurs de ce thème — en-tête, lignes alternées, bordures — au lieu des gris génériques. Des styles de repli ont été ajoutés pour toutes les familles de préréglages, si bien qu'un thème pas encore échantillonné hérite de l'aspect de sa famille.

Le catalogue des thèmes fournis s'élargit de nouvelles variantes, et le thème actif est appliqué dès la première image après un rechargement, sans le clignotement du thème précédent.

🖥️ En-tête redessiné et configurable

L'en-tête de l'application est désormais un composant du framework : les installations en héritent au lieu d'en maintenir une copie. Le bloc en haut à droite a été compacté — sélecteur de thèmes, clair/sombre, langue, notifications et espace utilisateur tiennent dans une carte qui se déplie au survol — et l'espace utilisateur affiche nom, rôle, licence et déconnexion.

Une nouvelle section Header & Menu dans les paramètres permet de choisir l'orientation du menu (horizontal au-dessus ou en dessous, vertical à gauche ou à droite), de charger un logo et de le positionner, et d'activer ou de désactiver le sélecteur de langue, celui de thèmes et les notifications. Il est aussi possible de désactiver la disposition automatique en plusieurs colonnes des entrées de sous-menu : les sous-menus longs deviennent alors défilables au lieu d'être tronqués.

🔗 Webhook Hub

Nouveau système pour intégrer l'application à des services externes, dans les deux sens.

En sortie : les événements sont mis en file et livrés de façon asynchrone, avec signature HMAC du payload, réessais à intervalle fixe ou exponentiel, file de dead letter pour les livraisons définitivement échouées et possibilité de rejouer une livraison. Chaque tentative est tracée dans les logs.

En entrée : l'endpoint POST /api/webhooks/inbound accepte les appels externes et les achemine selon une configuration de métadonnées — exécution SQL, appel HTTP ou invocation d'une méthode — avec protection anti-replay.

Sont également inclus des politiques de notification avec période de silence configurable, une API d'administration pour gérer les endpoints et une tâche du planificateur qui vide la file. Toute la configuration — endpoints, événements, abonnements, règles d'entrée — vit dans des tables de métadonnées : ajouter une intégration ne demande ni code dédié ni nouveau déploiement. La page « Webhook Hub » de la documentation intégrée décrit la procédure complète en 5 langues.

📈 Performance Inspector

Le framework peut collecter des métriques de fetch et de rendu pour chaque route, les agréger et les présenter dans un tableau de bord d'administration : moyenne, p95, maximum et nombre, avec une rétention de 7 jours et une activation route par route.

La fonction est désactivée par défaut et s'active avec AppSettings:enablePerformanceInspector, en hot-reload. À côté des métriques, un inspecteur de la qualité des données s'active par route depuis le props bag (extraProps.qualityInspector).

🤖 Chatbot : nouvelles actions et lecture du schéma

Le chatbot RAG gagne dix nouveaux types d'action et la capacité d'interroger la structure du projet.

  • Trois nouvelles surfaces contextuelles : pivot builder, éditeur de paramètres et report designer. Le chatbot propose des actions sur la page où l'on se trouve. Dans l'éditeur de paramètres, les modifications sont seulement préparées : l'enregistrement reste un geste explicite de l'utilisateur. Dans le dump envoyé au modèle, les valeurs réservées — chaînes de connexion, mots de passe, clés, licence — sont masquées, et une liste d'exclusion empêche de les écrire. Dans le report designer, un nouveau fichier horodaté est toujours généré, sans toucher au rapport ouvert.
  • Opérations sur les métadonnées : création de table, scaffolding de tables, vues et colonnes, déplacement d'entrées de menu. Les deux opérations non réversibles — suppression d'une colonne et d'une entrée de menu — exigent une confirmation explicite, vérifiée aussi côté serveur, ce qui vaut même lorsque la demande vient d'un client sans interface.
  • Introspection : le chatbot peut énumérer les connexions (les noms seulement, jamais les chaînes de connexion), les bases, les tables, les colonnes et l'arbre du menu. Sans ces lectures, il ne pouvait pas connaître les identifiants réels sur lesquels agir.

Une nouvelle page de documentation liste les prompts pris en charge, vérifiée face aux tests automatisés.

📊 Spreadsheet : visibilité des colonnes alignée sur la grille

Le spreadsheet respecte désormais les mêmes indicateurs de visibilité que la list grid : mc_hide_in_list, mc_hide_in_edit et mc_show_in_filters. Une colonne masquée dans la liste n'apparaît plus dans la feuille, et une colonne masquée en édition n'est plus modifiable dans les cellules.

🛡️ Sécurité

Hardening best-effort sur la génération assistée des rapports : le nom de fichier demandé est désormais validé en rejetant les chemins absolus et les caractères non autorisés, avec un contrôle qui se comporte de la même manière sous Windows et sous Linux — il s'appuyait auparavant sur une normalisation qui filtrait différemment sur les deux systèmes. L'erreur renvoyée distingue une configuration invalide d'un échec de génération, afin que les intégrateurs ne cherchent pas le problème au mauvais endroit.

🐛 Corrections notables

  • Calendrier, premier chargement : la vue affichait des données non filtrées sur l'intervalle affiché — typiquement aucun événement dans le mois courant, même en présence de rendez-vous. Le premier chargement partait avant que les champs de début et de fin configurés pour l'archétype soient disponibles, et aucune requête ultérieure ne corrigeait le tir. Les champs sont maintenant résolus avant la composition du filtre et, s'ils arrivent ensuite, les données sont redemandées une seule fois.
  • Scènes 3D avec une licence professional : les pages du concepteur et de la visionneuse 3D renvoyaient vers l'écran d'accès refusé, car la fonctionnalité n'était incluse dans aucun profil de licence. Elle fait désormais partie du profil professional.
  • Rapports sous Linux : la génération assistée d'un rapport échouait parce que les polices étaient traitées via une bibliothèque graphique disponible uniquement sous Windows.
  • Performance Inspector, agrégation : deux exécutions superposées du job d'agrégation — le tableau de bord le déclenche lors de son propre rechargement, et il peut aussi être lancé à la main — se terminaient par une erreur de clé dupliquée. De plus, la fenêtre des données brutes n'était pas alignée sur la limite du bucket journalier, si bien que le bucket le plus ancien était reconstruit à partir d'un sous-ensemble des événements.
  • Linux derrière un reverse proxy : les URL absolues générées par le backend perdaient le port et utilisaient le mauvais schéma lorsque l'installation est servie sur un port non standard ou uniquement en HTTP.
  • Oracle, enregistrement des scènes 3D : l'enregistrement échouait à cause d'un nom de paramètre réservé et de la conversion des valeurs numériques. Les deux sont corrigés, ainsi que le traitement des colonnes au nom en minuscules entre guillemets.
  • Oracle, exposition OData : les colonnes étaient forcées en majuscules au lieu d'utiliser le nom physique déclaré dans les métadonnées, rendant inaccessibles les entités aux noms mixtes.
  • PostgreSQL et Oracle, lookups dans les graphiques et les regroupements : le champ descriptif d'un lookup n'était pas résolu du nom logique au nom physique, et le regroupement affichait des valeurs vides ou erronées.
  • Chatbot, confirmations manquantes : à quatre endroits la demande de confirmation n'apparaissait jamais en raison d'un appel mal formé ; à deux de ces endroits la suppression (historique et sessions du chat) se faisait sans rien demander. Toute confirmation passe désormais par le même chemin et, en cas d'erreur, la réponse est « annuler ».
  • Import de métadonnées : les routes dont le champ base de données est vide — celles qui utilisent la base par défaut de l'application — ne pouvaient pas être importées, et l'erreur laissait penser à un problème de droits ou à une mauvaise base.
  • Visionneuse 3D : la scène occupait une bande horizontale au lieu de toute la hauteur de la page.
  • Interface, grille sur fond thématique : la zone sous la dernière ligne laissait transparaître l'arrière-plan de la page, donnant l'impression d'une grille trouée. La surface de la grille suit désormais le thème, en clair comme en sombre.

🔧 Mises à jour opérationnelles recommandées

  1. Revoir appsettings.json après la mise à jour : les nouvelles clés ont des valeurs par défaut prudentes et ne demandent aucune intervention, mais c'est le bon moment pour les parcourir.
  2. Performance Inspector : mettre AppSettings:enablePerformanceInspector à true pour l'activer ; il reste inactif si la clé est absente.
  3. Webhook Hub : aucune intervention n'est nécessaire pour le rendre accessible. Tables, routes d'administration et entrées de menu — regroupées dans un sous-menu « Webhook Hub » sous Administration — sont créées au premier chargement du menu, aussi bien sur une installation neuve qu'en mise à jour depuis une version antérieure. Reste à configurer l'intégration : en sortie trois lignes (l'endpoint avec URL de destination, secret partagé, délai et politique de réessai ; l'événement ; l'abonnement qui les relie), en entrée un endpoint de direction inbound et une règle d'acheminement. La signature voyage dans l'en-tête X-Wuic-Signature ; la procédure complète figure dans la page « Webhook Hub » de la documentation intégrée.
  4. Theme Builder : la table des thèmes est créée au premier enregistrement. Si vous utilisez des thèmes personnalisés, vérifiez l'export Excel d'une grille pour confirmer que les couleurs sont celles attendues.
  5. Chatbot : les nouvelles actions sont disponibles après le redémarrage du moteur RAG ; les opérations non réversibles exigent une confirmation et ne peuvent pas être appliquées sans elle.
  6. Linux derrière un reverse proxy : si l'installation répond sur un port non standard ou uniquement en HTTP, régénérer la configuration nginx ou aligner à la main le vhost existant sur proxy_set_header Host $http_host; et proxy_set_header X-Forwarded-Proto $scheme;. Les mises à jour ne réécrivent pas un vhost déjà présent.

v1.5.0

Retour à l'index

Version précédente publiée: 1.3.2 (18 juin 2026)
Backend: .NET 10 + IIS / Linux nginx
Frontend: Angular 21


Une version large qui rassemble des travaux sur plusieurs fronts. Le chatbot RAG dispose d'une configuration LLM simplifiée et unifiée, l'exécution d'un modèle local gratuit (Qwen via Ollama) devient une option de premier ordre et le moteur a été durci face aux particularités des modèles locaux ; un nouveau plugin Visual Studio Code, WUIC Assistant, apporte la même approche agentique dans l'éditeur. Le nouveau Scene3D Designer amène la création de scènes 3D dans l'application — matériaux PBR, effets de shader, lumières avec baking, physique et une visionneuse qui lie les objets aux données — et le rendu se choisit désormais entre WebGL et WebGPU. Le Workflow Designer reçoit un ensemble d'aide à la création (modèles de départ, validation du graphe, boîtes de dialogue guidées, aide en ligne), et le Designer de dashboards un ensemble d'améliorations d'édition.


🤖 Chatbot RAG — configuration LLM unifiée

La configuration du fournisseur LLM du chatbot a été consolidée autour d'une seule clé et d'une liste explicite de fournisseurs.

  • rag-llm-provider — anthropic / openai / openrouter / ollama, à définir explicitement (aucun fournisseur par défaut : si vide, le chatbot reste en retrieval-only et n'invoque aucun LLM). ollama est désormais une valeur de premier ordre : pointe vers un runtime local via rag-llm-base-url, au format compatible OpenAI.
  • rag-llm-api-key — la source unique de la clé, indépendante du fournisseur choisi. Remplace l'ancien couple llm-api-key / anthropic-api-key (acceptés uniquement comme fallback de migration). La valeur spéciale agent-sdk utilise l'Agent SDK (claude CLI) via subscription au lieu de l'API à l'usage, si installé.
  • rag-llm-base-url — override de l'endpoint ; obligatoire pour ollama (ex. http://HOST:11434/v1), optionnel pour les autres fournisseurs.
  • rag-llm-default-chat-model — id du modèle pour le fournisseur choisi.

Toutes les clés restent en hot-reload depuis appsettings.json : changer de fournisseur ou de modèle ne nécessite aucun redémarrage.

🧠 LLM local gratuit (Qwen via Ollama), sans clé API

Le chatbot peut désormais tourner entièrement sur un modèle local ouvert et gratuit — par exemple Qwen (qwen2.5-coder:32b) servi par Ollama sur sa propre machine ou sur le LAN — sans clé API et sans coût par token. Configuration typique dans appsettings.json -> AppSettings :

rag-llm-provider           = ollama
rag-llm-base-url           = http://HOST:11434/v1
rag-llm-api-key            = ollama
rag-llm-default-chat-model = qwen2.5-coder:32b

Un guide complet pour monter le serveur Ollama (Windows/Linux, exposition LAN, tuning du context, démarrage persistant) est inclus dans le paquet.

⚙️ Actions du chatbot fiables même avec des modèles locaux

Le moteur a été rendu tolérant aux particularités des modèles locaux qui — contrairement aux modèles commerciaux — ne respectent parfois pas à la lettre le format des appels d'outil. Le chatbot récupère désormais correctement l'action proposée même lorsque le modèle l'émet sous forme de texte ou avec des escapes JSON non standard. En pratique, les actions sur le designer et sur les métadonnées — boutons de table (bulk), boutons de ligne, styles conditionnels, callbacks, injection de composants dans le designer — sont proposées et appliquées de manière fiable même avec un LLM local.

🧩 Assistant agentique dans VS Code — WUIC Assistant

Le paquet inclut désormais un plugin pour Visual Studio Code, WUIC Assistant (llm-workspace/plugin/wuic-assistant.vsix) : un assistant qui connaît déjà les conventions du framework et opère directement sur le projet ouvert. Il génère des composants Angular (cards, dashboards avec tuiles KPI, list-grids avec navigation vers le formulaire d'édition), des composants alimentés par un endpoint .NET personnalisé, et propose des modifications de métadonnées (styles conditionnels, actions de table et de ligne, lookups). Chaque écriture passe par un aperçu avant confirmation.

Il utilise le même RAG local WUIC via le serveur MCP wuic-rag (démarré automatiquement) et le grounding déjà présent dans le projet, sans configuration manuelle du serveur MCP. Le modèle LLM est au choix — local via Ollama (Qwen, sans clé API) ou Anthropic.

Installation depuis le ZIP :

code --install-extension llm-workspace/plugin/wuic-assistant.vsix

Sinon, install-llm-workspace.ps1 l'installe. Puis Ctrl+Shift+P -> WUIC Assistant: Apri Chat ; le fournisseur se choisit dans les paramètres (wuicAssistant.provider = ollama ou anthropic).

🧊 Scene3D Designer (nouveauté)

Un nouveau concepteur 3D visuel sur la route #/scene3d_designer, publié en lecture seule via le Scene3D Viewer (#/scene3d_viewer/:scene_key). Il permet de composer une scène tridimensionnelle et d'en lier les objets aux données de l'application.

  • Palette et import: primitives (cube, sphère, plan, cylindre, cône, tore), groupes, lumières, caméra, texte 3D et Mesh Repeater (instances générées à partir des données). Import de modèles externes en glTF/GLB, OBJ, FBX, STL et DAE. La palette est extensible depuis les métadonnées avec des types personnalisés.
  • Matériaux PBR: metalness, roughness, émissif, opacité, wireframe, flat shading et faces ; pour le matériau physique également transmission, IOR, épaisseur et absorption volumétrique (verre coloré).
  • Effets de shader: un effet décrit en JSON (adossé à un schéma, avec complétion et une vue « structure ») est compilé pour le renderer actif ; sinon, des shaders GLSL écrits à la main sur le renderer WebGL.
  • Éclairage: lumières de scène avec ombres douces, baking de l'éclairage statique dans les couleurs de sommet (unlit) et — sur le renderer WebGL — un path tracer d'aperçu photoréaliste.
  • Animation et physique: contrôles de transport pour les clips des assets importés ; physique optionnelle par objet avec simulation Play/Stop dans le concepteur et lecture automatique dans la visionneuse.
  • Liaison aux données: chaque objet se lie à une route WUIC (avec enregistrement optionnel) et mappe des propriétés visuelles (libellé, couleur, visibilité) sur des colonnes ; un double-clic sur un objet lié dans la visionneuse ouvre le CRUD de l'enregistrement.
  • Miniatures automatiques: à l'enregistrement, la scène est capturée depuis le canvas et affichée en aperçu dans la liste « Charger la scène », sans configuration ni processus externe.

Les routes du concepteur et de la visionneuse nécessitent la fonctionnalité scene3d-designer. Les tables de support sont créées et mises à jour automatiquement à la première utilisation, sur toutes les bases de données prises en charge.

🖥️ Renderer WebGPU (opt-in)

Le rendu de la scène et de la visionneuse se choisit désormais entre WebGL (par défaut) et WebGPU (activable depuis la barre d'outils). Quand WebGPU n'est pas disponible dans le navigateur, le concepteur reste automatiquement sur WebGL. Le mode choisi est enregistré avec la scène et restauré à l'ouverture. Avec le renderer WebGPU actif, le baking des lumières s'exécute sur le GPU (ombres comprises), bien plus rapide sur les scènes denses ; les shaders GLSL écrits à la main et le path tracing restent disponibles sur le renderer WebGL.

🔀 Workflow Designer — création assistée

Le concepteur de workflows (#/workflow-designer) accompagne désormais la construction d'un processus de zéro.

  • Modèles de départ: « Nouveau depuis modèle » génère un graphe prêt pour les schémas courants (approbation simple, file claim/release, chaîne par seuils, tâches parallèles) : on choisit la route principale et — le cas échéant — le champ d'état, et le graphe, les actions et les transitions naissent déjà reliés.
  • Validation du graphe: « Valider le graphe » signale les problèmes avant l'enregistrement (start sans sortie, nœuds inaccessibles, action sans cible, condition vide, branche morte, timer ou split incomplets, permission avec un rôle inexistant). Cliquer sur un signalement cadre le nœud sur le canvas. L'enregistrement n'est jamais bloqué : en cas de problèmes ouverts, un récapitulatif apparaît avec « Enregistrer quand même ».
  • Configurations guidées: les boîtes de dialogue de timer et de tâches parallèles utilisent des menus déroulants et une autocomplétion des routes au lieu de champs libres saisis de mémoire.
  • Prise en main et aide: une liste des premières étapes sur un canvas vide, des info-bulles descriptives sur la palette et un « Guide rapide » avec une légende des formes et un glossaire des concepts (transition, garde, permission, action interne).

🎨 Designer de dashboards — édition plus rapide

  • Alignement sur la grille : activable depuis le menu d'actions du designer, il affiche la grille sur le canvas et aligne automatiquement le glissement, le redimensionnement et les drops depuis la palette. À l'activation, les éléments déjà présents sur le canvas sont eux aussi alignés sur la grille.
  • Flux normal / absolu : nouveau flag dans le menu d'actions (par défaut : flux normal, aucun changement pour les dashboards existants). En mode absolu, les éléments déposés se positionnent aux coordonnées du drop, hors du flux : en redimensionner un ne déplace pas les autres. Le drop dans un conteneur utilise le conteneur comme référence de position, et le runtime reconnaît automatiquement les dashboards enregistrés dans ce mode.
  • Raccourcis clavier : Suppr/Backspace supprime l'élément sélectionné, les flèches le déplacent, Ctrl+Z/Ctrl+Y annule/rétablit. En traçant un rectangle de sélection depuis une zone vide du canvas, on sélectionne plusieurs éléments : les flèches et Suppr agissent sur toute la sélection.
  • Import/export JSON et presets : le dashboard courant s'exporte en fichier JSON ré-importable (identique au contenu persisté), utile pour transférer des layouts entre environnements. Les presets enregistrent des layouts réutilisables sous un nom et se réappliquent en un clic.
  • Déplacer entre onglets : depuis le menu contextuel d'un élément dans un onglet, Déplacer vers un nouvel onglet crée un nouvel onglet et y migre l'élément (bindings et état préservés) ; Déplacer vers un autre onglet — disponible quand la tabview a plusieurs onglets — le déplace vers un onglet existant au choix. L'onglet de destination est activé automatiquement, tout comme un onglet fraîchement déposé.
  • Importer un dashboard/preset dans un élément : depuis le menu contextuel d'un conteneur, on importe un dashboard enregistré ou un preset directement dans l'élément ; les identifiants des éléments importés sont régénérés et les références internes (datasources comprises) remappées, sans collision avec le contenu existant.

🐛 Corrections de bugs notables

  • Designer — layout multi-colonnes : l'injection d'un layout multi-colonnes/multi-zones (ex. "3 colonnes, chacune avec une grille") proposée par le chatbot remplit désormais correctement toutes les zones. Auparavant, après la première cellule, les suivantes n'étaient pas résolues et les composants restaient vides.
  • Chatbot — whitelist des routes : lorsqu'on demande de lier un composant à une route au nom inexact (ex. "provincie" pour "stateprovinces"), le chatbot effectue désormais le match sémantique et propose l'action, au lieu de répondre à tort que la liste des routes est en cours de chargement.
  • Visionneuse 3D — navigation entre scènes: en ouvrant des scènes différentes à la suite depuis la même visionneuse, chacune charge désormais sa propre scène. Auparavant, la visionneuse pouvait continuer d'afficher la première scène ouverte.
  • Éditeur JSON adossé à un schéma: l'éditeur de code en mode JSON propose désormais une vue « structure » (activable par un interrupteur) pour ajouter et retirer des propriétés typées guidées par le schéma, sans écrire de JSON à la main.

🔧 Mises à jour opérationnelles recommandées pour les mises à niveau

  1. Pour utiliser un LLM local gratuit, renseigner dans appsettings.json -> AppSettings : rag-llm-provider=ollama, rag-llm-base-url, rag-llm-api-key (valeur indicative, ex. ollama) et rag-llm-default-chat-model.
  2. Migrer la clé du chatbot vers rag-llm-api-key : les anciennes llm-api-key et anthropic-api-key continuent de fonctionner en fallback, mais la configuration recommandée n'utilise que rag-llm-api-key.
  3. Pour l'assistant dans VS Code, installer le plugin depuis le ZIP : code --install-extension llm-workspace/plugin/wuic-assistant.vsix (ou le laisser installer par install-llm-workspace.ps1).
  4. Pour utiliser le Scene3D Designer, activez la fonctionnalité scene3d-designer dans la licence active. Les tables de support sont créées et migrées automatiquement à la première utilisation ; le renderer WebGPU est en opt-in depuis la barre d'outils, avec repli automatique vers WebGL.

v1.3.2

Retour à l'index

Version publiée précédente : 1.3.0 (11 juin 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Une version de consolidation autour du chatbot RAG introduit en 1.3.0 : le modèle conversationnel n'est plus lié à Anthropic — tout endpoint compatible OpenAI, y compris les runtimes locaux comme Ollama avec des modèles ouverts (Qwen), est désormais configurable et tourne sans clé API. À côté de cela, une série de correctifs sur l'installateur de first-run, le paquet sources et le scaffolding des métadonnées qui se manifestaient sur les installations neuves, ainsi qu'un workspace prêt pour les assistants IA de développement.


🤖 Chatbot RAG — fournisseur LLM flexible (y compris local et gratuit)

Le modèle conversationnel du chatbot est désormais indépendant du fournisseur. Outre Anthropic, les endpoints compatibles OpenAI sont pris en charge, ce qui inclut les runtimes locaux (p. ex. Ollama) : on peut exécuter des modèles ouverts et gratuits comme Qwen sur sa propre machine, sans clé API et sans coût par token.

  • rag-llm-provider — anthropic (par défaut) / openai / openrouter. Sélectionne le dialecte wire du fournisseur.
  • rag-llm-base-url — override de l'endpoint ; en l'indiquant vers l'URL d'un serveur local (p. ex. http://localhost:11434/v1 pour Ollama), le chatbot dialogue avec le modèle en local.
  • rag-llm-default-chat-model — id du modèle pour le fournisseur choisi (p. ex. un modèle Qwen sur Ollama).
  • llm-api-key — clé du fournisseur actif ; pour les runtimes locaux qui ne la valident pas, une valeur de remplacement (p. ex. ollama) suffit. L'historique anthropic-api-key reste valide quand rag-llm-provider=anthropic (aucune migration).

Toutes les clés sont en hot-reload depuis appsettings.json : changer de fournisseur ou de modèle ne nécessite aucun redémarrage.

Retrieval plus précis — le re-ranking des résultats a été affiné : le chatbot cite des sources plus pertinentes sur les requêtes en langage naturel.

Notifications de setup — au premier usage, le moteur .NET télécharge les modèles ONNX à la demande. L'administrateur reçoit désormais dans la cloche les notifications de démarrage / prêt / erreur du téléchargement, sur les quatre fournisseurs de BD, même lorsque l'initialisation est déclenchée par une requête sans utilisateur connecté.

Accélération GPU automatique — sur une machine avec GPU NVIDIA, le moteur utilise le GPU sans installer CUDA : au premier lancement, en plus des modèles ONNX, il télécharge à la demande le runtime CUDA 12 + cuDNN 9 nécessaire (~1,8 Go, une seule fois, uniquement si un GPU est présent) et le configure lui-même. Sans GPU → CPU, aucun téléchargement supplémentaire. Override manuel avec rag-engine-cuda-path.


🧩 Workspace prêt pour les assistants IA de développement

Les applications générées avec le framework incluent désormais une collection de fichiers markdown de contexte (description du projet, conventions, règles opérationnelles) à la racine du workspace. Ces fichiers rendent les assistants IA agentiques — Continue, Cline, Cursor et similaires — immédiatement conscients de la structure et des conventions WUIC, sans installer d'extension propriétaire. Tout client qui lit le contexte du workspace se comporte comme un assistant « WUIC-native ».


🐛 Correctifs notables

  • Installateur de first-run — mode non-tutoriel sur tous les fournisseurs de BD : l'installation avec scaffolding d'une base de données existante (sans les données d'exemple du tutoriel) a été corrigée et unifiée sur tous les fournisseurs pris en charge — SQL Server, MySQL, PostgreSQL et Oracle. Résolus les échecs dus aux différences de dialecte SQL, à la sélection de la base/du schéma cible et à la gestion des connexions qui apparaissaient hors du mode tutoriel.

  • Installateur de first-run — chemin par script SQL (non-BAK) : lors du provisioning de la BD de métadonnées via le script SQL incrémental (alternative au restore depuis un .bak), le parser des lots séparés par GO traitait mal certains séparateurs, faisant échouer la création du schéma sur les installations neuves. Le splitter a été corrigé et les installations par script se terminent correctement.

  • Paquet sources — moteur RAG .NET introuvable au runtime : dans le paquet sources (-src-), le moteur WuicRagEngine.dll était placé à la racine du paquet, tandis que l'exécutable, lancé depuis bin/, le cherchait à côté de lui — le chatbot RAG ne démarrait pas (« WuicRagEngine.dll introuvable »). Le loader recherche désormais le dossier rag-engine/ à plusieurs emplacements (sortie de build, content-root, répertoire courant) et trouve le moteur dans les deux layouts de déploiement.

  • First-run — persistance de la clé API du chatbot : la clé LLM saisie dans l'assistant de première installation est désormais écrite dans le appsettings.json canonique réellement lu par le runtime. Auparavant, dans certains layouts, elle pouvait atterrir dans une copie que le processus ne lit jamais, laissant le chatbot sans clé juste après l'installation.

  • Scaffolding des métadonnées — diagnostic et robustesse : le scaffolding des métadonnées de certaines tables pouvait échouer avec un message générique (« Unable to scaffold metadata table ») qui masquait la cause réelle. L'erreur SQL effective remonte désormais jusqu'à l'appelant, et le cas qui la provoquait est résolu.

  • Paquet sources — notifications temps réel en dev : dans le paquet -src-, le proxy du dev-server (ng serve) ne transférait pas les connexions WebSocket au backend ; le canal de notifications (/ws) tombait en timeout et les mises à jour n'apparaissaient qu'après un rechargement manuel de la page. Le proxy transfère désormais aussi les WebSockets : les notifications arrivent en temps réel.


📦 Paquets mis à jour

Paquet De À
WuicCore 1.3.0 1.3.2
Wuic.Webcore 1.3.0 1.3.2
WuicOData 1.3.0 1.3.2
RuntimeEfCore 1.3.0 1.3.2
Wuic.MySqlProvider 1.3.0 1.3.2
Wuic.PostgresProvider 1.3.0 1.3.2
Wuic.OracleProvider 1.3.0 1.3.2
wuic-framework-lib (NPM) 1.3.0 1.3.2

🔧 Actions opérationnelles recommandées pour la mise à jour

  1. Pour faire tourner le chatbot avec un modèle local et gratuit (p. ex. Qwen via Ollama) : définir rag-llm-provider=openai, rag-llm-base-url sur l'endpoint local (p. ex. http://localhost:11434/v1) et rag-llm-default-chat-model sur l'id du modèle ; renseigner llm-api-key avec une valeur de remplacement (p. ex. ollama) si le runtime ne la valide pas. Aucun redémarrage : les clés sont en hot-reload.
  2. Pour rester sur Anthropic, aucune action n'est nécessaire : anthropic-api-key continue de fonctionner avec rag-llm-provider=anthropic (par défaut).
  3. Le paquet sources (-src-) est plus léger : il n'inclut plus les DLL de framework redondantes à la racine, recréées par dotnet build à partir des paquets NuGet. Télécharger le nouveau -src- ne demande aucune action.
  4. Au premier usage du chatbot avec le moteur .NET, l'administrateur verra dans la cloche la progression du téléchargement des modèles ONNX. Attendre la notification « prêt » avant le premier Ask.
  5. Les nouvelles apps générées incluent automatiquement les fichiers de contexte pour assistants IA à la racine du workspace ; pour les apps existantes, ils peuvent être régénérés.

v1.3.0

Retour à l'index

Version précédente publiée : 1.2.1 (31 mai 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Version mineure centrée sur l'intégration du chatbot RAG côté framework : historique conversationnel persistant, gestion automatique du contexte, configuration hot-reload depuis appsettings.json et schéma cross-DBMS auto-appliqué au premier démarrage. À côté de la feature principale, quelques fixes au scaffolder de metadata et à la robustesse du repository chat sur MySQL/Oracle qui se manifestaient dans les scénarios de provisioning DB neufs.

Le chatbot est le premier composant WUIC avec état côté serveur (_rag_chat_sessions + _rag_chat_messages) qui s'étend sur les quatre providers supportés sans configuration manuelle du schéma. Le premier Ask détecte le provider, applique dans l'ordre les patches SQL incrémentaux et démarre. Avec cette release le stack de serving peut également tourner nativement sur .NET (moteur ONNX in-process), rendant le déploiement chez le client indépendant de Python.


🤖 Chatbot RAG — gestion du contexte end-to-end

Le composant <wuic-rag-chatbot> persiste désormais plusieurs sessions par utilisateur, avec historique complet de la conversation, summarization automatique du contexte et configuration via appsettings.json. La feature est opt-in : sans anthropic-api-key configurée, le chatbot reste inactif.

Sessions

  • Historique conversationnel persisté par utilisateur. La session survit aux reloads du navigateur et aux changements de route.
  • Popup de sélection des sessions ordonnées par updated_at décroissant, avec titre dérivé du premier prompt (tronqué à 100 caractères + tooltip complet).
  • Renommage inline avec persistance immédiate.

Gestion automatique du contexte

  • Visual cue % dans le header du chatbot : un cercle coloré qui indique la consommation de la fenêtre de contexte du modèle (vert <60% / jaune 60-80% / orange 80-90% / rouge >90%). La valeur provient des tokens réellement consommés par l'API Anthropic et est persistée par tour, donc elle survit au reload.
  • Auto-compact pre-Ask : quand la conversation dépasse le seuil configurable (défaut 30 tours) et qu'au moins 10 tours ne sont pas encore résumés, le backend lance un compact best-effort en arrière-plan avant le prochain Ask. Le résumé mis à jour est injecté dans le system prompt pour les tours futurs.
  • Compact à la demande : l'utilisateur peut forcer un compact via le slash command /compact ou en cliquant sur le cercle cue.
  • Memory facts : le modèle lui-même peut "épingler" des faits high-priority via tool use (remember_fact/forget_fact). Les faits restent dans le system prompt même après un compact (max 20, eviction FIFO).
  • Follow-up questions : le modèle suggère jusqu'à 3 questions de suivi, rendues comme des chips cliquables sous la réponse. Clic = pré-remplit l'input box (n'envoie pas automatiquement).

Configuration appsettings.json

  • anthropic-api-key — clé API Anthropic, hot-reload. Non hard-coded, ne jamais committer dans le repo.
  • anthropic-default-chat-model — claude-haiku-4-5-20251001 (200k, défaut) / claude-sonnet-4-5-20250929 / claude-opus-4-5. Détermine la fenêtre de contexte et le driver du visual cue.
  • anthropic-auto-compact-threshold — entier >=0, défaut 30. Mettre à 0 pour désactiver l'auto-compact (le /compact manuel reste disponible).

Auto-migration cross-DBMS

Le schéma chat history (5 patches incrémentaux) est appliqué de manière idempotente au premier Ask, sur le provider configuré (MSSQL / MySQL / PostgreSQL / Oracle). Aucun step DBA requis sur les installations existantes.


🛠️ Actions que le chatbot peut appliquer au projet

Au-delà de répondre en langage naturel, le chatbot peut proposer des modifications concrètes au projet sous forme de chips d'action avec un bouton "Appliquer". Chaque chip indique ce qu'il va faire (route cible, code généré, justification) et l'utilisateur décide de l'appliquer ou non. Rien n'est exécuté sans un clic explicite.

Types d'action supportés :

  • Actions toolbar et de ligne — ajoute des boutons personnalisés à la toolbar d'une <wuic-list-grid> ou à l'action d'une ligne unique, avec des callbacks JavaScript générés. Exemples : "ajoute une action qui exporte les lignes sélectionnées en CSV", "mets un bouton Approuver sur chaque ligne".
  • Styles conditionnels de ligne et de colonne — applique des classes CSS à une ligne ou à une cellule individuelle selon une condition JS. Exemples : "surligne en rouge les lignes avec échéance dépassée", "mets un fond vert sur la cellule statut quand elle vaut 'OK'".
  • Formule d'affichage de colonne — remplace la représentation d'une colonne en liste par un template HTML/Angular personnalisé (badge, icône, lien, pourcentage coloré). Exemple : "affiche priorité comme un badge vert/jaune/rouge".
  • Formule du titre de formulaire — calcule dynamiquement le titre du formulaire d'édition d'un enregistrement à partir de son contenu. Exemple : "le titre doit être Client {raison_sociale}".
  • Valeur par défaut et validation personnalisée — génère des callbacks pour les valeurs par défaut à l'ouverture du formulaire (pré-remplissage de champs) ou pour la validation complexe (cross-field, regex personnalisés). Exemples : "default date_creation = aujourd'hui", "valide que email se termine par @entreprise.fr".
  • Selection-changed et lifecycle callbacks — hooks sur les événements du formulaire (changement de sélection d'enregistrement, before-save, after-save, after-delete) pour des side-effects personnalisés : refresh des datasources liés, notifications, audit log applicatif.
  • Modifications de metadata — applique des modifications directes aux metadata de table/colonne (caption, tri, masquer en list/edit, validations de base) sans passer par l'éditeur de metadata manuel.
  • Snippets SQL dans les metadata (super-admin) — écrit des fragments SQL bruts dans les champs de metadata qui sont concaténés à l'exécution dans les requêtes auto-générées : JOIN personnalisé sur la route, clause SELECT personnalisée sur une colonne, formule de colonne calculée, expression d'affichage de lookup. Exemples : "calcule total sur orders comme price × quantity", "ajoute un join à payments sur invoice_id". Le chatbot connaît le dialecte du provider actif (mssql/mysql/postgres/oracle) et génère du SQL avec le quoting/syntaxe corrects. Opération gated D3 : nécessite des privilèges super-admin côté backend, avec audit log automatique sur _error__logs pour chaque application.

🎨 Action nouvelle : layout designer depuis le langage naturel

Quand l'utilisateur se trouve sur la page Designer d'un dashboard, le chatbot expose une nouvelle famille d'actions qui agit directement sur le canvas du designer (pas sur les metadata persistés).

Patterns de prompt supportés :

  • "ajoute une grid liée à la route cities" → injecte DATASOURCE + DATAREPEATER configurés et liés ;
  • "crée un layout tabulaire 2×2" → injecte une <table> 2×2 avec des cellules prêtes à recevoir d'autres composants ;
  • "mets un splitter vertical avec 3 zones" → injecte un SPLITTER configuré ;
  • "change la couleur du panneau en haut à droite en rouge" → modifie la propriété backgroundColor du composant identifié ;
  • "ajoute une colonne à la table" / "supprime la ligne 2" → modifie cols/rows du composant TABLE sélectionné ;
  • "supprime le KPI Chiffre d'affaires" → supprime un composant du canvas par son nom.

Le chatbot connaît le catalogue complet des 31 outils du designer (groupes HTML, DATA, CONTAINER) et leurs propriétés éditables. Quand l'utilisateur mentionne une route metadata avec un nom approximatif ("provincies" au lieu de "stateprovinces"), le chatbot fait du fuzzy-match contre les routes disponibles dans le projet et affiche le vrai nom résolu dans la justification de l'action.

Les modifications restent sur le canvas du designer jusqu'au clic sur "Enregistrer le dashboard" — pas d'écritures BDD automatiques, le résultat visuel est toujours vérifié avant le commit. L'undo/redo du designer couvre également les actions injectées par le chatbot.


⚙️ Moteur RAG natif .NET (déploiement sans Python)

Le stack de serving du chatbot RAG peut désormais tourner entièrement sur .NET, sans serveur Python séparé ni virtual environment sur la machine cible. Les modèles de retrieval (embeddings + reranker) sont chargés in-process via ONNX Runtime, avec accélération GPU (CUDA) détectée automatiquement et fallback transparent sur CPU.

  • Activation via appsettings.json : rag-use-dotnet-engine=true sélectionne le moteur .NET ; la valeur par défaut false conserve le comportement précédent.
  • rag-engine-device (auto / cpu / cuda) choisit le device d'inférence ; rag-engine-profile contrôle le niveau de rédaction des sources citées dans les réponses.
  • Au premier démarrage les artefacts nécessaires (modèles ONNX + index) sont téléchargés on-demand, ainsi le paquet de base reste léger.

Résultat pratique : le déploiement chez le client est .NET uniquement — aucune installation Python ni dépendances natives supplémentaires au-delà du runtime .NET. L'appel au modèle conversationnel et la pipeline de retrieval et d'actions sont identiques entre les deux moteurs.


🐛 Corrections notables

  • Documentation des callbacks alignée sur le runtime : le recueil de callbacks décrivait des signatures ne correspondant pas au comportement réel dans deux cas. Le default value callback écrit la valeur dans le record (record[field.mc_nome_colonna] = ...) et le return est ignoré ; la validation custom reçoit (record, field, vr, wtoolbox) et communique le résultat avec un return booléen (false bloque la sauvegarde) plus vr.message pour le texte affiché. Les exemples précédents, basés sur validateResult(...) et sur un return pour le default value, produisaient des callbacks qui ne s'appliquaient pas. Documentation corrigée dans les cinq langues.

  • Fiabilité des actions proposées par le chatbot : pour les requêtes d'action le chatbot émet désormais de façon déterministe la chip d'action correspondante, et réessaie automatiquement en cas de rate-limit transitoire du modèle conversationnel au lieu de dégrader silencieusement vers une réponse texte uniquement.

  • Scaffolder de metadata — distinction date vs datetime consolidée : follow-up du fix introduit en 1.2.1 sur les types temporels générés. Le parser des types source couvre désormais aussi les variantes DDL atypiques (MySQL DATETIME(0) sans precision, PostgreSQL timestamp nu sans qualifieur time-zone, Oracle TIMESTAMP(n) avec precision explicite) — tous continuent à mapper correctement vers le UI type datetime en préservant la composante time à la sauvegarde.

  • Suggest sur champs metadata — mc_suggest_value_callback normalise désormais le return value : le callback configurable côté DB pouvait retourner une promise ou une valeur synchrone, mais le parser runtime n'acceptait que le cas synchrone. Résultat : le suggest échouait silencieusement dans les callbacks async. La normalisation attend désormais Promise.resolve(callback(...)) de manière uniforme.

  • Repository chat — Guid cross-driver : le driver MySQL.Data matérialise une colonne CHAR(36) comme Guid quand le flag OldGuids est false (défaut à partir de la version 6.6 du connector), provoquant InvalidCastException sur GetString. Même risque sur Oracle avec storage RAW(16). La lecture du correlation id a désormais une cascade de fallback (GetGuid → GetString → GetValue avec switch sur runtime type) — robuste sur les quatre providers indépendamment de la configuration du driver.

  • Repository chat — connexion MySQL non ouverte : le gateway MySQL retournait une new MySqlConnection(cs) sans appeler Open(), asymétrique par rapport aux gateways PostgreSQL et Oracle. Le premier ExecuteNonQueryAsync du schema auto-apply échouait avec "Connection must be valid and open". Ajout d'un OpenConnectionToConnectionString symétrique, aligné avec les autres providers.


📦 Paquets mis à jour

Package De À
WuicCore 1.2.1 1.3.0
Wuic.Webcore 1.2.1 1.3.0
WuicOData 1.2.1 1.3.0
RuntimeEfCore 1.2.1 1.3.0
Wuic.MySqlProvider 1.2.1 1.3.0
Wuic.PostgresProvider 1.2.1 1.3.0
Wuic.OracleProvider 1.2.1 1.3.0
wuic-framework-lib (NPM) 1.2.1 1.3.0

🔧 Mises à jour opérationnelles recommandées

  1. Pour activer le chatbot RAG, ajouter à appsettings.json la clé anthropic-api-key (et optionnellement anthropic-default-chat-model et anthropic-auto-compact-threshold). Le backend relit les clés en hot-reload — pas besoin de restart.
  2. Aucun step DBA requis sur les installations existantes : au premier Ask du chatbot, le schéma chat history (_rag_chat_sessions + _rag_chat_messages avec toutes les colonnes) est appliqué idempotente sur le provider configuré dans MetaDataSQLConnection. L'auto-migration couvre les installations neuves et partiellement migrées.
  3. Si l'installation tourne sur MySQL / PostgreSQL / Oracle, vérifier que la connection string pointe vers le provider correct et que l'utilisateur dispose des privilèges ALTER TABLE sur le schéma metadata (nécessaires une seule fois, au premier démarrage).
  4. Pour monitorer la consommation de la fenêtre de contexte, le cercle cue % dans le header du chatbot est le driver visuel immédiat. Au-delà de 80%, il vaut la peine de lancer un compact manuel (/compact ou clic sur le cue) pour réduire la latence des tours suivants.
  5. Pour faire tourner le chatbot RAG sans Python sur la machine cible, définir rag-use-dotnet-engine=true dans appsettings.json (optionnellement rag-engine-device et rag-engine-profile). Au premier démarrage les artefacts d'inférence sont téléchargés automatiquement.

v1.2.1

Retour à l'index

Version précédemment publiée : 1.2.0 (27 mai 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Release de maintenance centrée sur une classe de bugs latents qui affectaient les champs datetime et decimal dans des scénarios cross-DBMS / cross-locale. La plupart des utilisateurs sur workstation en locale italienne ont été touchés au moins une fois — la composante time des timestamps était tronquée à minuit lors de INSERT et UPDATE, et les décimaux avec séparateur non invariant produisaient ORA-01722 sur Oracle dès que la session ODP.NET héritait de la culture italienne de Windows.

Les fixes sont transverses aux 4 providers supportés (MSSQL, MySQL, PostgreSQL, Oracle) et tous les tests roundtrip end-to-end passent au vert aussi bien en locale de session DB anglaise (en-US) qu'italienne (Italiano dmy, lc_time=Italian_Italy.1252).


🐛 Corrections de bugs notables

  • Composante time tronquée lors de INSERT/UPDATE de champs DATETIME2 / DATETIME(n) / TIMESTAMP : le scaffolder des métadonnées collapsait tous les types temporels de la DB source sur l'unique type UI date. Conséquence : une colonne SQL Server DATETIME2(3) (ou MySQL DATETIME(3), PostgreSQL timestamp without time zone, Oracle TIMESTAMP(0)) était traitée comme date pure et le framework émettait '20261231' au lieu de '20261231 23:59:58' lors de INSERT/UPDATE — l'heure saisie via l'UI était perdue à l'enregistrement. Le scaffolder distingue maintenant date (date pure) de datetime (date + heure) et l'enregistrement préserve la composante time à la seconde près. La précision sub-seconde (.fff) reste tronquée intentionnellement pour rester cohérente avec le date-time picker UI qui ne l'expose pas.

  • Oracle ORA-01722 : nombre non valide sur champs NUMBER(p,s) depuis une workstation italienne : les providers émettaient les valeurs numériques quoted en string dans les INSERT/UPDATE (ex. VALUES (..., '9876.4321', ...)). Oracle convertissait ensuite la string en nombre en utilisant NLS_NUMERIC_CHARACTERS de la session, qu'ODP.NET dérive de la CurrentCulture du thread .NET : en culture italienne le séparateur décimal est , et . devient le séparateur de groupe → '9876.4321' était interprété comme expression de groupe invalide. Les valeurs numériques (decimal, float, double, numeric) sont désormais émises comme literals SQL non quoted : les literals numériques Oracle utilisent toujours . comme point décimal indépendamment de NLS.

  • Oracle ORA-00904 : identificateur invalide sur tables avec identificateurs quoted-lowercase : une table créée avec DDL CREATE TABLE "my_table" ("id" NUMBER, ...) (lowercase quoted, case-preserving) n'était pas lisible par le framework. La logique de quoting reconnaissait les mixed-case et les reserved keywords mais traitait les all-lower comme "safe identifier" et les émettait bare (Oracle case-folde les identificateurs bare en UPPER), provoquant un mismatch avec le physique "id". Les identificateurs all-lowercase sont désormais préservés avec un quoting explicite.

  • Parsing/formatting locale-invariant des dates et timestamps côté serveur : le path parse/emit de DateTime sur Oracle et PostgreSQL utilisait la CurrentCulture du thread. Le parsing essaie maintenant d'abord InvariantCulture et ne retombe sur CurrentCulture qu'en cas de besoin ; le formatting pour les clauses SQL (TO_TIMESTAMP(...) / literal yyyy-MM-dd HH:mm:ss) utilise toujours InvariantCulture. Effet user-visible : le round-trip reste bit-perfect indépendamment du CultureInfo.CurrentCulture du process backend.

  • Oracle ORDER BY sur PK lowercase : la clause ORDER BY ajoutée automatiquement sur la clé primaire émettait le nom de colonne sans passer par la logique de quoting → produisait ORA-00904 sur les tables avec PK "id" lowercase quoted. La PK passe maintenant par le même quoting que toutes les autres colonnes.


🗄️ Compatibilité DB cross-locale

Les tests roundtrip end-to-end couvrent désormais les combinaisons provider × session DB suivantes :

Provider Session DB testée Résultat
MSSQL @@LANGUAGE=Italian, date_format=dmy, Latin1_General_CI_AS OK
MySQL lc_time_names=en_US, utf8mb4_0900_ai_ci, time_zone=SYSTEM OK
PostgreSQL DateStyle=ISO,DMY, lc_time=Italian_Italy.1252 OK
Oracle NLS_LANGUAGE=AMERICAN, NLS_TERRITORY=AMERICA, NLS_NUMERIC_CHARACTERS=., OK

Les dates sont garanties invariantes end-to-end (2026-12-31T23:59:58.000 reste 2026-12-31T23:59:58.000 indépendamment de la session DB et de la CurrentCulture backend), tout comme les décimaux (9876.4321 reste 9876.4321).


📦 Packages mis à jour

Package De À
WuicCore 1.2.0 1.2.1
Wuic.Webcore 1.2.0 1.2.1
WuicOData 1.2.0 1.2.1
RuntimeEfCore 1.2.0 1.2.1
Wuic.MySqlProvider 1.2.0 1.2.1
Wuic.PostgresProvider 1.2.0 1.2.1
Wuic.OracleProvider 1.2.0 1.2.1
wuic-framework-lib (NPM) 1.2.0 1.2.1

v1.2.0

Retour à l'index

Version publiée précédente: 1.1.0 (13 mai 2026)
Backend: .NET 10 + IIS / Linux nginx
Frontend: Angular 21


Cette version étend le framework à deux nouveaux SGBD — PostgreSQL et Oracle — et corrige un bug du filtre Spreadsheet qui apparaissait sur les routes avec server-side operations activées lorsque la colonne était de type lookup.

  • Provider PostgreSQL et Provider Oracle: tous deux installables en drop-in (postgresql.dll / oracle.dll à côté de WuicCore.dll), utilisables comme data store ou comme metadata store, avec parité fonctionnelle vis-à-vis de MSSQL et MySQL.
  • Filtre Spreadsheet sur colonnes lookup en mode server-side: le popup affiche maintenant les descripteurs de la lookup (par ex. Woodgrove Bank Crandon Lakes) et applique le filtre en utilisant l'ID de clé étrangère, éliminant l'erreur SQL que les providers à typage strict produisaient.

🗄️ Provider PostgreSQL

Drop-in compatible avec PostgreSQL 14+ (testé sur 16). Installation: déposer postgresql.dll à côté de WuicCore.dll dans le physical path du site IIS, ou dans le répertoire de publish du binaire Linux. Le wizard de setup firstRun expose automatiquement "PostgreSQL" dans le dropdown DBMS dès qu'il détecte la DLL.

Couverture fonctionnelle. Toutes les surfaces core du framework opèrent nativement sur PG avec la même sémantique que les versions MSSQL/MySQL: CRUD, server-side paging, sorting, grouping, agrégations, lookup autocomplete, OData, scheduled jobs, audit, notifications, retry policy, concurrence optimiste, validations, callbacks/events, import/export XLS, export PDF, multi-tenant.

Types PG-spécifiques supportés. boolean (mappé automatiquement depuis/vers le stockage interne smallint utilisé pour la parité avec MSSQL/MySQL), varchar/text, numeric, integer/bigint, timestamp, date, bytea (upload binaire), geometry (PostGIS — affichage cartographique via ST_AsText).

Fichiers préconfigurés dans le paquet.

  • appsettings.postgres.json / appsettings.linux.postgres.json / appsettings.multi-tenant.postgres.json — environnements self-contained prêts à l'emploi, activables avec ASPNETCORE_ENVIRONMENT=postgres.
  • dbms/scripts/first-run/*.postgres.sql — bootstrap metadata + DDL/DML tutoriel WideWorldImporters.

🗄️ Provider Oracle

Drop-in compatible avec Oracle 19c / 21c / Free 23c. Installation oracle.dll selon le même procédé que le provider PostgreSQL; "Oracle" apparaît automatiquement dans le dropdown firstRun.

Couverture fonctionnelle. Identique à PostgreSQL — toutes les surfaces core avec la même sémantique que les versions MSSQL/MySQL.

Longueur des identifiants. Oracle 11g/12.1 (30 caractères max) n'est pas encore supporté — les alias lookup générés par le framework dépassent la limite. Oracle 12.2+ (128 caractères) est le plancher de support.

Fichiers préconfigurés dans le paquet.

  • appsettings.oracle.json / appsettings.linux.oracle.json / appsettings.multi-tenant.oracle.json.
  • dbms/scripts/first-run/*.oracle.sql — bootstrap metadata + tutoriel.

🐛 Corrections notables

  • Filtre popup Spreadsheet sur colonnes lookup quand md_server_side_operations=true: le popup colonne funnel de <wuic-list-spreadsheet> sur une colonne lookupByID affichait des IDs numériques nus (par ex. 1, 4, 5) au lieu des descripteurs (par ex. Woodgrove Bank Crandon Lakes). Sur PG/Oracle l'application du filtre produisait une erreur SQL (42601 ilike %% sur PostgreSQL, ORA-00904 sur Oracle) parce que le client transmettait la chaîne descriptive contre la colonne FK numérique. Le serveur émet désormais le descripteur joint (<entity>___<dataTextField>__<colName>) à côté de l'ID FK et le client affiche le descripteur dans le popup mais transmet l'ID raw comme filter value: le WHERE col = <id> reste numérique et cross-SGBD-safe. Aucune action requise côté consumer.

📦 Paquets mis à jour

Package De À
WuicCore 1.1.0 1.2.0
Wuic.Webcore 1.1.0 1.2.0
WuicOData 1.1.0 1.2.0
RuntimeEfCore 1.1.0 1.2.0
Wuic.MySqlProvider 1.1.0 1.2.0
Wuic.PostgresProvider — 1.2.0
Wuic.OracleProvider — 1.2.0
wuic-framework-lib (NPM) 1.1.0 1.2.0

🔧 Mises à jour opérationnelles recommandées pour ceux qui mettent à jour

  1. Pour les utilisateurs MSSQL ou MySQL: aucune action requise. Le fix du filtre Spreadsheet s'applique à tous les providers de manière transparente après le premier refresh du client.
  2. Pour activer PostgreSQL: copier postgresql.dll (ainsi que ses dépendances runtime — Npgsql.dll, Npgsql.EntityFrameworkCore.PostgreSQL.dll, Microsoft.Extensions.Logging.Abstractions.dll) dans le physical path du site IIS ou dans le répertoire de publish Linux, redémarrer le backend. Sélectionner PostgreSQL dans le wizard firstRun, ou pointer ASPNETCORE_ENVIRONMENT=postgres pour utiliser appsettings.postgres.json préconfiguré.
  3. Pour activer Oracle: même procédure — oracle.dll + Oracle.EntityFrameworkCore.dll + Oracle.ManagedDataAccess.dll. Vérifier que la version du DB cible est ≥ 12.2 (contrainte de longueur des identifiants).
  4. Cache client: après la mise à jour, un hard refresh du navigateur (Ctrl+F5) suffit à aligner le client avec le nouveau contrat du filtre popup. Aucune invalidation de metadata côté serveur requise.

v1.1.0

Retour à l'index

Version précédente publiée : 1.0.20 (12 mai 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Saut mineur : cette version introduit deux capacités structurelles qui modifient le modèle de déploiement du framework.

  • Multi-tenant : une seule instance du framework route les données et les métadonnées de N entreprises sur N connexions BD différentes. Configuration tenant par tenant via les colonnes Aziende.Connessione_DB_Dati / Aziende.CONNESSIONE_DB_Meta ; routage transparent au niveau applicatif via TenantContext (AsyncLocal, survit aux frontières Task/scheduler).
  • Localisation du menu par langue : les entrées de menu (mm_display_string_menu) ne contiennent plus de libellés italiens codés en dur, mais des clés stables avec namespace menu.<scope>.<slug>, résolues à l'exécution par la pipe translate d'Angular contre _wuic_translations. Le changement de langue depuis le sélecteur utilisateur met à jour toutes les entrées sans F5.

🌐 Gestion multi-tenant

Une seule installation du framework peut désormais servir plusieurs entreprises (« tenants ») avec des données et métadonnées physiquement isolées sur des BD différentes, sans nécessiter de répliquer l'application ni de partitionner les reverse-proxies par hôte.

Modèle de données. Le routage tenant→connexions est défini sur deux colonnes de la BD de métadonnées primaire :

  • Aziende.Connessione_DB_Dati — nom d'une entrée dans ConnectionStrings pour la BD applicative du tenant
  • Aziende.CONNESSIONE_DB_Meta — nom d'une entrée dans ConnectionStrings pour la BD de métadonnées du tenant

Les colonnes contiennent le nom de l'entrée, pas la chaîne littérale. La rotation des credentials se fait en éditant appsettings.<env>.json, sans toucher à la BD.

Activation. Flag dans appsettings.json (section AppSettings) :

"multiConnectionEnabled": "true"

Avec le flag false (par défaut) le comportement reste single-tenant, identique aux versions précédentes. Avec le flag true chaque requête HTTP authentifiée résout l'AziendaId depuis l'utilisateur connecté et route GetOpenConnection vers les connection strings du tenant correspondant.

Routage transparent. Tous les points d'accès BD du framework (MetaService.*, scheduler, scaffolding, AsmxProxy CRUD, callbacks personnalisés) consultent TenantScope.CurrentAziendaId via AsyncLocal, propagé par le middleware HTTP post-authentification. Les jobs en arrière-plan et les callbacks personnalisés déclarent explicitement le tenant avec using (TenantScope.Push(aziendaId)) { ... } lorsqu'ils s'exécutent en dehors du contexte de requête.

Cache tenant-aware. Les clés Application[] côté serveur et les caches locaux de métadonnées sont automatiquement suffixés par AziendaId lorsque le flag est actif, évitant le bleed de métadonnées entre tenants.

Routage de login. La table _login_index(username_hash, id_azienda) sur la BD primaire mappe username → tenant pour le fallback de MetaService.login : après authentification, le cookie k-user porte azienda_id dans le payload et le middleware crée le TenantScope correct à chaque requête suivante.

Propagation de scaffold. L'action « Scaffold table » propage de manière idempotente les métadonnées de la table à tous les tenants listés dans Aziende. La propagation s'exécute avec un TenantScope explicite sur chaque cible et est idempotente : ré-exécutable, n'applique que les changements manquants.

Fichiers préconfigurés dans le package :

  • appsettings.multi-tenant.mssql.json / appsettings.multi-tenant.mysql.json — environnement self-contained avec 6 connection strings d'exemple (1 primary + 5 tenants) et multiConnectionEnabled=true. Activer avec ASPNETCORE_ENVIRONMENT=multi-tenant.mssql.
  • dbms/scripts/multi_tenant_aziende_connessioni_mssql.sql / _mysql.sql — DDL pour ajouter les deux colonnes à Aziende sur des BD existantes.

🗺️ Localisation du menu par langue

Les entrées de menu sont désormais traduites dynamiquement selon la langue de l'utilisateur, sans avoir besoin de dupliquer les enregistrements _metadati__menu par locale.

Architecture. Le champ mm_display_string_menu de _metadati__menu contient une clé stable avec namespace (menu.admin.roles, menu.crm.opportunities, menu.fleet.vehicles, ...). Le template du composant menu Angular applique la pipe translate sur item.label et la clé est résolue à l'exécution depuis le dictionnaire _wuic_translations filtré par la langue courante.

Schéma de clé.

menu.<scope>.<slug>
   │       └── slug snake_case (ex. column_styles, opportunities)
   └── scope = root | admin | demo | crm | fleet | invoice
  • menu.root.* — parents top-level (Administration, Application, Accueil, ...)
  • menu.admin.* — 36 entrées système partagées (Rôles, Designer, Styles colonne, Workflow Designer, ...)
  • menu.demo.* — contenu démo WideWorldImporters
  • menu.crm.* / menu.fleet.* / menu.invoice.* — entrées spécifiques au domaine du tenant

Avantage par rapport au modèle précédent.

  • L'ancien modèle utilisait le texte italien du libellé comme clé de traduction (Aziende, Customers, Ruoli). Cela causait des case-mismatches silencieux (Ruoli vs ruoli, Stili Tabella vs Stili tabella) car la pipe translate est case-sensitive alors que _wuic_translations a une collation case-insensitive : le premier MERGE qui entrait fixait le casing pour toujours, et les INSERTs ultérieurs avec casing divergent devenaient des no-ops silencieux.
  • Le nouveau modèle à clés stables est case-déterminé (tout en minuscules par convention), namespacé par scope, et n'entre plus en collision avec d'autres ressources qui pourraient utiliser le même texte italien (ex. un libellé de bouton « Ruoli » dans un dropdown est une clé différente de menu.admin.roles).

5 langues supportées. it-IT, en-US, fr-FR, es-ES, de-DE. Les traductions vivent dans _wuic_translations (format standard : language, resource, translation). Le changement de langue depuis le dropdown utilisateur en haut à droite relit le dictionnaire pour la nouvelle langue et redessine le menu sans F5.

Fallback à l'exécution. Langue courante → en-US → it-IT → clé brute. Si vous voyez menu.admin.roles littéral à l'écran cela signifie que la clé n'a pas été seedée dans aucune des 5 langues.

Les anciennes clés italiennes dans _wuic_translations ne sont pas touchées par la mise à jour : elles peuvent être consommées par d'autres points de l'app (instant('Aziende') en code-behind, headers de list-grid, page titles) et restent valides.


🐛 Corrections de bugs notables

  • Formulaires d'édition dynamiques — Tabs et widgets dans les templates md_edit_template en production : dans les builds de production les templates HTML personnalisés associés à une route via md_edit_template ne rendaient pas correctement les Tabs de PrimeNG 21 (les labels apparaissaient comme du texte concaténé sans le chrome du composant) et les field-editors n'affichaient que des placeholders <!----> à la place des inputs. Cause : le compilateur runtime utilisé par le framework pour les templates dynamiques requiert l'énumération explicite des composants standalone disponibles dans le template, et MetadataProviderService.widgetDefinition.dynamicFormImports était incomplet. Ajoutés à la baseline TabsModule + Tabs/TabList/Tab/TabPanels/TabPanel, FieldsetModule, DataRepeaterComponent, DataSourceComponent, ImageWrapperComponent. Aucune action requise sur les apps consumer une fois le paquet wuic-framework-lib mis à jour.

🎁 Applications gratuites désormais disponibles

À partir de cette version, trois applications complètes sont distribuées gratuitement sur le framework — disponibles dans la section « Free apps » de la page Downloads :

  • CrmApp — CRM B2B auto-hébergé : registre clients, pipeline d'opportunités avec kanban drag-and-drop, activités (appels / réunions / emails), tableau de bord par rôle. (Lire l'article)
  • FatturazioneElettronica — Facturation électronique italienne : éditeur de factures FatturaPA v1.2, signature CADES-BES, validation XSD, 4 fournisseurs SDI interchangeables (DirectPec gratuit via PEC, ArubaPec / FatturePec / PecIt commerciaux), conservation légale, registres IVA et liquidation. (Lire l'article)
  • FlottaMezzi — Gestion de flotte : anagraphe véhicules / conducteurs, échéances automatiques (taxe / contrôle technique / assurance / révision / permis), feed géolocalisation OBD/GPS, carte en direct, agrégation coûts €/km par véhicule et par conducteur, reporting TCO. (Lire l'article)

Chaque application est disponible en trois formats : ZIP IIS avec base tutorielle (prête à restaurer), ZIP IIS sans base, ZIP sources.

Modèle de licence. Les applications gratuites sont GRATUITES telles que livrées — le binaire <App>.dll du ZIP embarque une ressource host-binding-license qui autorise le runtime framework sans clé externe. Ce n'est que si vous recompilez l'application depuis les sources (par exemple pour ajouter un nouveau contrôleur ou modifier une signature publique) qu'une licence WUIC Developer ou Professional est requise : la recompilation produit un binaire avec une identité différente, perd le bundling, et le framework retombe sur le contrôle de licence fingerprint standard.

Étendre les applications gratuites sans recompiler le binaire est couvert par le bundling : ajout de métadonnées via SQL, composants Angular dans le wwwroot, jobs dans la table scheduler, hooks personnalisés via appsettings.json:customCrudHookClass.


📦 Packages mis à jour

Package De À
WuicCore 1.0.20 1.1.0
Wuic.Webcore 1.0.20 1.1.0
WuicOData 1.0.20 1.1.0
RuntimeEfCore 1.0.20 1.1.0
wuic-framework-lib (NPM) 1.0.20 1.1.0

🔧 Mises à jour opérationnelles recommandées pour ceux qui mettent à jour

  1. Pour ceux qui veulent activer le multi-tenant (opt-in) : appliquer le script DDL dbms/scripts/multi_tenant_aziende_connessioni_mssql.sql (ou _mysql.sql) pour ajouter les colonnes Connessione_DB_Dati et CONNESSIONE_DB_Meta à Aziende. Renseigner les lignes Aziende avec les noms des entrées ConnectionStrings de appsettings.json. Définir AppSettings.multiConnectionEnabled = "true". Redémarrer le backend.
  2. Pour ceux qui restent single-tenant : aucune action requise. Sans multiConnectionEnabled=true le routage tenant est désactivé et le comportement est bit-identique à la 1.0.20.
  3. Localisation du menu — refresh des métadonnées : après la mise à jour, exécuter une fois POST /api/Meta/AsmxProxy/MetaService.invalidateMetadataRuntime pour recharger le dictionnaire menu côté client. Alternativement, se déconnecter et se reconnecter.
  4. Localisation du menu — migration d'un projet existant : pour les projets venant d'une version précédente avec libellés italiens dans _metadati__menu.mm_display_string_menu, appliquer deux étapes SQL idempotentes : (a) UPDATE _metadati__menu SET mm_display_string_menu = '<menu.scope.slug>' WHERE mm_display_string_menu = '<ancien libellé>' pour chaque entrée, selon le schéma menu.<scope>.<slug> documenté ci-dessus ; (b) INSERT/MERGE INTO _wuic_translations (language, resource, translation) 5 lignes par nouvelle clé (une par langue). Les anciennes lignes dans _wuic_translations avec resource = texte italien restent dans la BD et peuvent toujours être consommées par d'autres callers (instant(), headers de list-grid).
  5. Hot reload backend en dev : si vous développez avec dotnet watch, le task backend: kill dll lockers requiert désormais pwsh 7+ (plus Windows PowerShell 5.x). Le script C# inline pour Restart Manager utilise la syntaxe Dictionary<,> correctement parsée seulement en PS 7+.

v1.0.20

Retour à l'index

Version précédente publiée : 1.0.19 (4 mai 2026)
Backend : .NET 10 + IIS / Linux nginx
Frontend : Angular 21


Version de consolidation après la 1.0.19, centrée sur des corrections de bugs ayant un impact direct sur l'édition et l'affichage (INSERT avec triggers INSTEAD OF, champs numériques remis à 0 au blur, calendrier vide à la première navigation, préservation du SQL custom dans les rapports) et sur un alignement du composant carte avec les nouvelles API Google Maps : finalisation des options de l'archetype map, migration vers la Routes API pour le snap-to-roads, suppression de la dépendance à la drawing library dépréciée.


🐛 Corrections de bugs notables

  • INSERT avec triggers INSTEAD OF : les tables avec triggers INSTEAD OF INSERT perdaient la PK retournée par l'instruction externe (OUTPUT INSERTED.<pk> retournait 0 ou NULL car le trigger détournait l'INSERT). Correctif : l'INSERT généré par _Metadati_methods utilise désormais une variable de table (@__inserted_pk avec OUTPUT ... INTO) comme canal principal et revient sur IDENT_CURRENT('<table>') quand le trigger consomme l'instruction externe. Résout également le SQL Server msg 334 (OUTPUT INSERTED sans INTO n'est pas autorisé sur des tables avec triggers activés).
  • field-editor number — reset à 0 au blur : lorsque la colonne de métadonnées avait mc_min_value ou mc_max_value définis, le champ numérique était remis à 0 au blur au lieu de conserver la valeur saisie. La vérification de plage se déclenchait avant le roundtrip de parsing, lisant une valeur intermédiaire non numérique et la rabattant à 0. Comportement correct : la valeur est confirmée et clampée aux limites uniquement si elle est effectivement hors plage, sinon elle reste inchangée.
  • Archetype map — options complétées : l'archetype du composant carte reçoit trois propriétés qui comblent des manques UX courants :
    • polyline — overlay polyline pour le suivi de trajets (enregistrements GPS historisés). Regroupement par champ (groupByField), tri (orderByField), couleur par enregistrement/par groupe, snap-to-roads optionnel, dots de waypoint distincts du path interpolé.
    • clickableIcons — pass-through à google.maps.MapOptions.clickableIcons. Quand false, Google Maps n'ouvre plus sa propre info window intégrée sur les POIs (boutiques, arrêts, adresses), qui interceptait sinon les clics destinés aux marker custom.
    • markerColorField — couleur du PinElement lue depuis un champ du record (CSS #rrggbb). Ignoré si le record a déjà customMarkerImageSrcField défini (l'image/SVG est prioritaire).
  • Google Maps Directions API — dépréciée : DirectionsService est déprécié depuis le 2026-02-25. Le snap-to-roads des polylines utilise désormais la nouvelle Routes API (google.maps.routes.Route.computeRoutes), avec fallback automatique sur le legacy DirectionsService (fonctionnel jusqu'au 2027-02-25) pour les clés non encore migrées. Mapping legacy travel mode → routes inchangé (DRIVING/WALKING/BICYCLING). Batching automatique à 25 waypoints par appel.
  • Google Maps Drawing API — supprimée : la drawing library (google.maps.drawing) est dépréciée depuis 2025-08 et supprimée dans les versions de Maps JavaScript API publiées à partir de mai 2026. La logique DrawingManager sur MapListComponent n'était que des stubs console.log (aucune feature de dessin réellement persistée) et a été retirée. PointFilterComponent (filtre géo par zone/cercle dans les list-grids) a été réécrit avec des handlers manuels click+mousemove — même UX (polygone via plusieurs clics, cercle via centre+rayon, double-clic pour fermer), indépendant de la library dépréciée.
  • Rapports — préservation du SQL custom via le sentinel __autogenerated : les rapports avec un SQL custom qui aliasaient des colonnes non enregistrées dans les métadonnées perdaient les joins/colonnes, car la dynamic query auto-générée écrasait la query utilisateur. Correctif cross-DBMS (MSSQL, MySQL, PostgreSQL, Oracle) : chaque SELECT auto-généré injecte désormais 1 AS [__autogenerated] comme première colonne ; la pipeline de métadonnées détecte le token au runtime et préserve la query custom lorsque le sentinel n'est pas présent. Permet des layouts Stimulsoft qui lisent des colonnes non enregistrées en tant que métadonnées (typique dans les templates de facturation/PEC où le SQL dérive des colonnes calculées).
  • Calendrier — événements invisibles à la première navigation : <wuic-scheduler-list> affichait un calendrier vide quand l'utilisateur naviguait directement vers #/<route>/scheduler (FullCalendar s'initialisait avec data=[] avant l'arrivée de la réponse async ; un F5 le peuplait car le cache de session livrait les données avant le mount). Correctif : synchronisation explicite des événements via API (removeAllEvents() + addEvent()) après le rendu du calendrier, contournant le binding [events]="data" peu fiable du wrapper FullCalendar 6.x Angular sur les updates post-mount.

📦 Paquets mis à jour

Paquet De À
WuicCore 1.0.19 1.0.20
Wuic.Webcore 1.0.19 1.0.20
WuicOData 1.0.19 1.0.20
RuntimeEfCore 1.0.19 1.0.20
wuic-framework-lib (NPM) 1.0.19 1.0.20

🔧 Actions opérationnelles recommandées pour la mise à jour

  1. Exécuter dotnet ef database update si vous utilisez les migrations EF.
  2. Si vous utilisez le snap-to-roads sur les polylines de carte : vérifiez que votre clé Google Maps API a la Routes API activée en plus de la Directions API. Sans la Routes API, le framework retombe sur le legacy DirectionsService, encore fonctionnel mais dans la fenêtre de dépréciation (sunset 2027-02-25).
  3. Si vous dépendiez de la drawing toolbar standard de MapListComponent (aucun use case connu — les handlers étaient des stubs) : la toolbar a été retirée. Aucune action requise pour les filtres géo dans les list-grids — PointFilterComponent conserve la même UX avec une implémentation interne.
  4. Pour utiliser le nouveau overlay polyline sur une route carte : ajouter la configuration { enabled: true, groupByField, orderByField, ... } à md_props_bag.archetypes.map.polyline via le designer ou un patch de métadonnées.

v1.0.19

Retour à l'index

Version publiée précédente: 1.0.7 (26 avril 2026)
Backend: .NET 10 + IIS / Linux nginx
Frontend: Angular 21


En six jours de développement intensif, WUIC fait un saut significatif: du déploiement unique sur Windows IIS à une plateforme multi-runtime (Windows + Linux natif), avec un système unifié de gestion typée des erreurs, crash reporting centralisé, authentification LDAP, et un tour de hardening best-effort sur la surface applicative.


🛡️ Sécurité

Hardening best-effort sur toute la surface applicative: throttling de l'authentification, renforcement des en-têtes HTTP standards (HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy), gestion environment-aware de CORS et Swagger, réduction de l'info disclosure dans les réponses d'erreur, gating granulaire des endpoints administratifs, contrôles supplémentaires sur le chemin SQL runtime. Les configurations par défaut sont maintenant plus conservatrices même pour les déploiements demo/staging, avec override explicite disponible via AppSettings.


🚨 Crash Reporting (end-to-end)

Nouveau système de crash reporting auto-installé qui envoie les stack traces .NET + JavaScript à un receiver self-hosted.

  • Capture passive: les exceptions unhandled sont collectées automatiquement, dédupliquées via stack canonicalization et mises en file async — aucun impact sur la latence des requêtes.
  • Receiver privé: errors.wuic-framework.com accepte les uploads signés avec RSA license signature (zéro clé API à gérer).
  • Consentement RGPD: opt-in explicite géré dans AppSettings, configurable depuis l'éditeur de settings.
  • Activation: CrashReporting:Enabled=true dans appsettings.json + consentement RGPD via UI.

🐧 Déploiement Linux (nouveau)

WUIC est désormais installable sur Ubuntu/Debian entièrement automatisé, avec stack supporté:

  • Runtime .NET + MSSQL Server ou MySQL/MariaDB.
  • Python 3.12 + environnement RAG.
  • Secrets via systemd credentials.
  • Reverse proxy nginx avec TLS Let's Encrypt.
  • Smoke test post-installation qui valide backend, RAG et proxy.

Le tarball Linux inclut appsettings.linux.mssql.json et appsettings.linux.mysql.json préconfigurés pour les deux stacks supportés, plus un README avec la procédure pas à pas.


🔐 Authentification LDAP

Le login WUIC supporte maintenant le bind LDAP comme alternative à la BDD:

  • Configuration via la section Authentication:Ldap:* dans appsettings.json (server, base DN, bind template).
  • Auto-provisioning utilisateurs: la ligne locale est créée/mise à jour au premier login avec les données LDAP.
  • Fallback BDD: si LDAP est unreachable et Authentication:Ldap:FallbackToDbOnFailure=true, le login retombe sur la BDD traditionnelle (admin/admin reste toujours accessible pour la recovery).

Compatible avec Active Directory, OpenLDAP et annuaires Novell.


🗄️ Provider MySQL (Wuic.MySqlProvider 0.8.3)

Support MySQL/MariaDB étendu à parité avec le primary MSSQL:

  • Couverture complète des tests fonctionnels (audit, CRUD client-side, concurrency, conditional styling, import-export, OData, retry, stored procedures, traductions, validations).
  • Fix de bugs spécifiques Linux: collation par défaut, quirks de JSON_TYPE, paging hints.

🚦 Système unifié d'erreurs (typed exceptions)

Refactor complet de la gestion des erreurs applicatives:

  • WuicException comme type de base pour toutes les exceptions applicatives typées (partie de l'API publique du framework).
  • WuicErrorCodes: catalogue de 27 codes stables (errors.auth.unauthenticated, errors.metadata.props_bag.malformed, errors.db.sql_exception, errors.report.render_failed, etc.).
  • JSON envelope stable pour toutes les réponses d'erreur: { ok, errorCode, args, traceId, fallbackMessage }. Permet au client d'afficher des messages localisés au lieu de stack traces techniques.
  • Traductions built-in en IT/EN/DE/ES/FR/JA pour tous les codes connus.
  • Mapping automatique des exceptions runtime connues (SqlException, AuthenticationException, JsonException, etc.) vers les codes typés.

📊 Export Excel

Réécriture du path d'export bulk au format .xlsx sur pipeline producer/consumer et OpenXmlWriter streaming. L'impact concerne surtout les datasets volumineux (dizaines de milliers de lignes et plus).

  • Streaming OpenXML à la place du DOM-build incrémental : typiquement 50× plus rapide sur les exports bulk, footprint mémoire contenu même au-delà d'un million de lignes.
  • Pipelining DB-read / xlsx-write sur buffer borné : les lectures DB ne sont plus bloquées par le temps de compression de la feuille.
  • Notifications de progress agrégées via un canal dédié : plus une task par update, fini le storm WebSocket pendant les exports longs.
  • Split automatique sur plusieurs feuilles quand la limite Excel de 1 048 576 lignes par feuille est dépassée. Le message de fin indique le nombre de feuilles générées.

Aucune action requise : le path est actif par défaut pour tous les exports .xlsx déclenchés depuis la toolbar de list-grid (Export XLS) et depuis les API server-side.


🐛 Bug fix notables

  • Gating isSuperAdmin: corrigée la vérification des permissions sur plusieurs endpoints qui confondaient précédemment isAdmin (rôle per-user) avec isSuperAdmin (rôle source of truth).
  • OData CRUD: corrigées les sérialisations edge case (Decimal→string, DateTime UTC roundtrip, navigation properties).
  • First-run wizard: le bootstrap initial consomme maintenant correctement IConfiguration (plus de dépendance au legacy app.config).
  • Crash reporting forwarding: bug du 2026-04-28 résolu — les exceptions MVC handled ne contournent plus le middleware crash reporter.

📦 Paquets mis à jour

Paquet De À
WuicCore 1.0.13 1.0.19
Wuic.Webcore 1.0.13 1.0.19
WuicOData 1.0.13 1.0.19
RuntimeEfCore 1.0.13 1.0.19
Wuic.MySqlProvider 0.7.x 0.8.3
wuic-framework-lib (NPM) 1.0.11 1.0.19

🔧 Étapes opérationnelles recommandées pour ceux qui mettent à jour

  1. Exécuter dotnet ef database update si on est sur EF migrations.
  2. Vérifier appsettings.json: le système lit maintenant aussi AppSettings:AllowedOrigins (array string) et AppSettings:registrationEnabled (boolean kill-switch). Défauts sûrs si non spécifiés.
  3. Si on utilise LDAP, configurer la section Authentication:Ldap:* dans appsettings.json.
  4. Pour le déploiement Linux: utiliser le tarball dédié et suivre le README inclus.
  5. Pour activer le crash reporting outgoing: définir CrashReporting:Enabled=true dans appsettings.json + accepter le consentement RGPD via UI.