Skip to content

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èreStatut
1Les paramètres UUID dans le controller workflow sont validés via ParseUUIDPipe sur tous les endpoints
2Les champs success et status de WorkflowRunResponseDto sont cohérents — le frontend utilise uniquement status
3Le premier poll après POST /run attend un délai initial avant de démarrer
4Un objet vide {} reçu dans workflow-canvas.sync.js ne remplace pas la configuration existante d'un nœud
5WorkflowEnterpriseMissingException retourne HTTP 403 et non 400
6La valeur headerRowIndex est validée avec Number.isFinite() avant d'être utilisée dans le parsing

3. Périmètre fonctionnel

Backend

FichierModification
back/src/api/workflows/workflows.controller.tsAjout de ParseUUIDPipe sur tous les @Param UUID (workflowUuid, runUuid, nodeUuid). Validation Number.isFinite() sur headerRowIndex.
back/src/api/workflows/dto/workflow-run.dto.tsSuppression du champ success: boolean redondant dans WorkflowRunResponseDto.
back/src/exceptions/workflow.exceptions.tsWorkflowEnterpriseMissingException étend désormais ForbiddenException (HTTP 403) au lieu de BadRequestException (HTTP 400).
back/src/api/workflows/workflow-debug-run.service.tsfindNodeResultInSession() appelle désormais purgeExpiredSessions() pour libérer les schémas de staging orphelins sur tous les points d'entrée.

Frontend

FichierModification
front/src/composables/useWorkflowRun.jsStatut final déterminé uniquement par result.status ('success' ou 'warning'), sans recours à result.success.
front/src/pages/admin/workflows/workflow-run-progress.format.jsSuppression du fallback sur result.success pour calculer overallStatus.
front/src/pages/admin/workflows/workflow-run-live.jsAjout 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.jsProtection contre l'écrasement de config par un objet vide {} : seuls undefined et les objets non vides sont propagés.
front/src/composables/useWorkflowEditorAutosave.jsAjout 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

FichierCas couverts
front/src/__tests__/.../workflow-run-live.spec.jsfetchStatus n'est pas appelé avant l'expiration du délai initial
front/src/__tests__/.../workflow-canvas.sync.spec.jsObjet vide ne remplace pas la config existante ; null explicite est accepté
front/src/__tests__/.../workflow-run-progress.format.spec.jsoverallStatus dérivé uniquement de status ; fallback 'failed' si absent
back/src/exceptions/workflow.exceptions.spec.tsWorkflowEnterpriseMissingException est une instance de ForbiddenException avec statut 403

Corrections de tests préexistants

FichierProblème corrigé
back/src/api/workflows/staging/workflow-staging-load.service.spec.tsTimeout 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.jsGuillemets typographiques (') utilisés comme délimiteurs de chaînes JS — remplacement par des apostrophes droites.