Appearance
BDD-156 — Corrections de sécurité et stabilité du module Workflow
1. User Story
En tant qu'utilisateur du module Workflow, je veux que l'application soit stable et sécurisée, afin d'éviter des pertes de configuration, des erreurs d'état et des failles de validation.
2. Critères d'acceptance
| # | Critère | Statut |
|---|---|---|
| 1 | Les paramètres UUID dans le controller workflow sont validés via ParseUUIDPipe sur tous les endpoints | ✅ |
| 2 | Les champs success et status de WorkflowRunResponseDto sont cohérents — le frontend utilise uniquement status | ✅ |
| 3 | Le premier poll après POST /run attend un délai initial avant de démarrer | ✅ |
| 4 | Un objet vide {} reçu dans workflow-canvas.sync.js ne remplace pas la configuration existante d'un nœud | ✅ |
| 5 | WorkflowEnterpriseMissingException retourne HTTP 403 et non 400 | ✅ |
| 6 | La valeur headerRowIndex est validée avec Number.isFinite() avant d'être utilisée dans le parsing | ✅ |
3. Périmètre fonctionnel
Backend
| Fichier | Modification |
|---|---|
back/src/api/workflows/workflows.controller.ts | Ajout de ParseUUIDPipe sur tous les @Param UUID (workflowUuid, runUuid, nodeUuid). Validation Number.isFinite() sur headerRowIndex. |
back/src/api/workflows/dto/workflow-run.dto.ts | Suppression du champ success: boolean redondant dans WorkflowRunResponseDto. |
back/src/exceptions/workflow.exceptions.ts | WorkflowEnterpriseMissingException étend désormais ForbiddenException (HTTP 403) au lieu de BadRequestException (HTTP 400). |
back/src/api/workflows/workflow-debug-run.service.ts | findNodeResultInSession() appelle désormais purgeExpiredSessions() pour libérer les schémas de staging orphelins sur tous les points d'entrée. |
Frontend
| Fichier | Modification |
|---|---|
front/src/composables/useWorkflowRun.js | Statut final déterminé uniquement par result.status ('success' ou 'warning'), sans recours à result.success. |
front/src/pages/admin/workflows/workflow-run-progress.format.js | Suppression du fallback sur result.success pour calculer overallStatus. |
front/src/pages/admin/workflows/workflow-run-live.js | Ajout d'un délai initial (await sleep(pollIntervalMs)) avant le premier appel de poll, évitant un 404 si la base n'a pas encore persisté le run. |
front/src/pages/admin/workflows/workflow-canvas.sync.js | Protection contre l'écrasement de config par un objet vide {} : seuls undefined et les objets non vides sont propagés. |
front/src/composables/useWorkflowEditorAutosave.js | Ajout d'un flag isUnmounting : les timers d'autosave ne sont plus planifiés ni exécutés après le démontage du composant, évitant des callbacks orphelins sur un composant déjà détruit. |
4. Comportement détaillé
Validation UUID (P0)
Avant ce correctif, un paramètre de route comme :workflowUuid acceptait n'importe quelle chaîne. Avec ParseUUIDPipe, toute valeur non conforme au format UUID v4 est rejetée avec une erreur 400 avant même d'atteindre le service.
Unification du statut final (P0)
Le DTO WorkflowRunResponseDto contenait deux champs redondants pouvant se contredire :
success: boolean— suppriméstatus: WorkflowRunFinalStatusDto— conservé comme source unique de vérité
Le frontend utilise désormais status === 'success' || status === 'warning' pour déterminer le succès.
Délai initial de poll (P1)
Avant ce correctif, le premier appel GET /runs/:runUuid/status était émis immédiatement après POST /run, avant que la base de données n'ait persisté le run, provoquant un 404 intermittent. L'ajout d'un await sleep(pollIntervalMs) avant la boucle garantit que le premier poll n'est émis qu'après un intervalle.
Protection config nœud (P1)
Vue Flow peut émettre des mises à jour partielles (drag, redimensionnement) avec config: {}. Sans protection, cet objet vide écrasait silencieusement la configuration sauvegardée du nœud. La correction traite {} comme "pas de changement" et préserve la valeur précédente.
Code HTTP 403 (P2)
WorkflowEnterpriseMissingException représente une absence de contexte entreprise — une erreur d'autorisation, pas une erreur de paramètre. Le code HTTP correct est 403.
Validation headerRowIndex (P2)
Number("abc") retourne NaN en JavaScript. Sans Number.isFinite(), ce NaN était transmis au service de parsing, provoquant un comportement indéfini. La correction applique un fallback à 1 pour toute valeur non numérique.
5. Tests
| Fichier | Cas couverts |
|---|---|
front/src/__tests__/.../workflow-run-live.spec.js | fetchStatus n'est pas appelé avant l'expiration du délai initial |
front/src/__tests__/.../workflow-canvas.sync.spec.js | Objet vide ne remplace pas la config existante ; null explicite est accepté |
front/src/__tests__/.../workflow-run-progress.format.spec.js | overallStatus dérivé uniquement de status ; fallback 'failed' si absent |
back/src/exceptions/workflow.exceptions.spec.ts | WorkflowEnterpriseMissingException est une instance de ForbiddenException avec statut 403 |
Corrections de tests préexistants
| Fichier | Problème corrigé |
|---|---|
back/src/api/workflows/staging/workflow-staging-load.service.spec.ts | Timeout Jest trop court (5 s par défaut) sur un test chargeant 200 000 lignes en parallèle — ajout d'un timeout explicite de 30 s. |
front/src/__tests__/.../WorkflowEditorPage.spec.js | Guillemets typographiques (') utilisés comme délimiteurs de chaînes JS — remplacement par des apostrophes droites. |
