From 97ab56f92872b0f4e590b92513dcfa24f18d6c25 Mon Sep 17 00:00:00 2001 From: Arthur Ria Date: Mon, 24 Aug 2026 17:34:38 +0200 Subject: [PATCH] L2.3 : garde-fous get_workflow_details et search_logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deux anomalies préexistantes au lot 1, mesurées le 24/08/2026 : - get_workflow_details({}) renvoyait success: true avec le premier workflow du cache : getWorkflowDetails() comparait w.Id/w.Code/w.Name, clés qui n'existent pas sur les objets AD réels (minuscules, D5) — undefined === undefined matchait. Clés mortes supprimées (id et name seuls existent, les parseInt sur des GUID étaient morts aussi), garde d'entrée rejetant workflow_id absent avec renvoi vers search_workflows. - search_logs({}) plantait en "Cannot read properties of undefined (reading 'toLowerCase')" : garde d'entrée nommant "keyword" avec un exemple d'appel. Le wrapper D23 rejette déjà ces appels via required — les gardes côté code restent, la validation SDK n'étant pas garantie pour les appelants directs des services. Mesures : - via le protocole, les deux appels {} -> "Paramètre(s) requis manquant(s) pour ... " (wrapper D23) - gardes appelées en direct (sans wrapper) : getWorkflowDetails(undefined) jette "workflow_id est requis (id ou nom exact du workflow)..." ; search_logs({}) répond success: false avec le message nommant keyword - get_workflow_details avec un id réel (2e workflow du cache, pas le premier) -> objet brut complet ($id, validFrom, ..., data), id/name conformes à la recherche ROADMAP : L2.3 retirée, lot 2 soldé. Co-Authored-By: Claude Fable 5 --- ROADMAP.md | 26 +++----------------------- src/services/workflow-service.js | 18 ++++++++++-------- src/tools/log-tools.js | 6 ++++++ 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 0ef98a2..97a5bf8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -12,31 +12,11 @@ contient que ce qui reste à faire. --- -## Lot 2 — Correctif de fond - -La cause racine commune du lot (résolution `Name` -> `TableName` via l'API -Metadata) est livrée — la règle et ses mesures vivent en **D21**. - -### L2.3 — Arguments manquants : deux garde-fous - -Découverts lors de la révision du lot 1 (24/08/2026), en bouclant sur les 23 -outils avec des arguments vides. Préexistants au lot 1 (vérifié sur le diff) : - -- `get_workflow_details` sans `workflow_id` renvoie `success: true` avec **le - premier workflow du cache**. Cause : `getWorkflowDetails()` - (`workflow-service.js`) compare `w.Code === workflowId` — or `Code`, `Id`, - `Name` n'existent pas sur les objets réels (clés minuscules, D5), donc - `undefined === undefined` matche. Supprimer les clés mortes de la - comparaison et rejeter un `workflow_id` absent avec un message actionnable. -- `search_logs` sans terme de recherche renvoie - `Search failed: Cannot read properties of undefined (reading 'toLowerCase')` - — le contrat d'erreur tient, mais le message viole la convention 4 - (actionnable). Garde d'entrée avec le nom du paramètre attendu. - ---- - ## Lot 3 — Ergonomie et documentation +Le lot 2 (résolution `Name` -> `TableName`, rejet des paramètres inconnus, +garde-fous d'arguments manquants) est livré — voir **D21** et **D23**. + ### L3.1 — Bornage des sorties volumineuses - `get_system_parameters` : ajouter `limit` / `offset`, aujourd'hui absents diff --git a/src/services/workflow-service.js b/src/services/workflow-service.js index df010f6..bfb3149 100644 --- a/src/services/workflow-service.js +++ b/src/services/workflow-service.js @@ -132,22 +132,24 @@ async function searchWorkflows(query, category = null, limit = 50) { * @param {string|number} workflowId - Workflow ID */ async function getWorkflowDetails(workflowId) { + // Garde d'entrée : sans elle, un workflow_id absent matchait le premier + // workflow du cache (undefined === undefined sur les clés mortes ci-dessous). + if (workflowId == null || workflowId === '') { + throw new Error('workflow_id est requis (id ou nom exact du workflow). Utilisez search_workflows pour le trouver.'); + } + const workflows = await fetchAllWorkflows(); - // Try to find by Id, id, Code, code, Name, or name + // Clés réelles de l'API AD (minuscules, D5) : id, name. Les variantes + // Id/Code/Name n'existent pas sur ces objets — les comparer faisait matcher + // undefined === undefined dès que workflow_id manquait. const workflow = workflows.find(w => w.id === workflowId || - w.Id === workflowId || - w.id === parseInt(workflowId) || - w.Id === parseInt(workflowId) || - w.Code === workflowId || - w.code === workflowId || - w.Name === workflowId || w.name === workflowId ); if (!workflow) { - throw new Error(`Workflow not found: ${workflowId}`); + throw new Error(`Workflow not found: ${workflowId}. Utilisez search_workflows pour trouver l'id ou le nom exact.`); } return workflow; diff --git a/src/tools/log-tools.js b/src/tools/log-tools.js index 30078f7..e265946 100644 --- a/src/tools/log-tools.js +++ b/src/tools/log-tools.js @@ -174,6 +174,12 @@ async function searchLogs(args) { const { keyword, max_results = 50, context_lines = 2 } = args; try { + // Garde d'entrée : sans elle, un keyword absent plantait en + // "Cannot read properties of undefined (reading 'toLowerCase')". + if (typeof keyword !== 'string' || keyword.trim() === '') { + throw new Error('Le paramètre "keyword" (mot-clé à rechercher) est requis. Exemple : search_logs({"keyword": "Execute error"}).'); + } + const result = await logService.searchLogs(keyword, max_results, context_lines); return {