L2.1 : résout entity_type via l'API Metadata (D21)

Context.{entity_type} attend le TableName du Metadata, pas le nom
d'entité de l'AD (Container -> Containers, mais Alias -> Alias) : un nom
faux partait en HTTP 500 de compilation LINQ. Nouveau service
entity-resolver.js : table Name|TableName (insensible à la casse) ->
TableName, agrégée sur les applications déployées (via
GET /configuration/applications — les applications sans contexte
requêtable n'y figurent pas et n'apportent 0 entité Metadata), cache TTL
partagé, invalidation par onSwitch (D8). Branché dans wms-query-service
(query/count/schema/search) et call_query_api.

Nom inconnu -> échec avant tout appel réseau de requête, suggestions
proches + renvoi vers get_entity_metadata. Metadata injoignable -> le
nom passe tel quel avec un warning dans la réponse.

Mesures (LIMAGRAIN, via le protocole) :
- query_wms_entities("Container", limit 1) -> succès, 1 ligne, résolu
  Containers
- query_wms_entities("Alias") -> succès, invariant (pas de pluriel)
- query_wms_entities("Item") -> "Item" n'existe pas dans le modèle
  Reading. Proches : RFMenuItems, Sites. 288 entités disponibles —
  aucune ligne [API] POST dans stderr
- count_wms_entities("Product") -> 51160
- get_entity_schema("Container") et call_query_api("Container") : mêmes
  résolutions
- 288 TableName distincts sur 5 applications, aucun conflit
  Name -> TableName (mesuré le 24/08/2026)

Docs : D21 dans DECISIONS.md ; CLAUDE.md (piège retiré des points
ouverts, liste d'entités corrigée Aliases -> Alias, entity-resolver dans
la structure) ; exemple singulier/pluriel dans wms://query-examples ;
ROADMAP allégée (cause racine + L2.1 + L3.3 livrés).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Arthur Ria
2026-08-24 17:28:27 +02:00
parent 8c5792da52
commit cb625a7918
8 changed files with 276 additions and 75 deletions
+4 -54
View File
@@ -12,51 +12,10 @@ contient que ce qui reste à faire.
---
## Cause racine commune
Le MCP interpole `entity_type` dans `Context.{entity_type}` **sans aucune
validation** (vérifié : aucune liste blanche dans le code). Or le nom attendu
par le contexte de lecture n'est pas le nom d'entité de l'Application
Dictionary.
L'API Metadata (`GET /Metadata/Entities`, **232 entités**) donne la
correspondance exacte :
| `Name` (renvoyé par `search_ad_elements`) | `TableName` (attendu par `Context.`) |
|---|---|
| `Container` | `Containers` |
| `Product` | `Products` |
| `ContainerType` | `ContainerTypes` |
| `Alias` | `Alias`**invariant, pas de pluriel** |
| `Item` | *n'existe pas dans le modèle Reading* |
Ce n'est donc pas une règle de pluralisation : c'est un mapping, et seul
`TableName` fait foi. `TableName` est unique sur les 232 entités.
Conséquences déjà constatées :
- une session utilisant les noms de l'AD (singuliers) déclenche un **HTTP 500**
sur chaque requête ;
- la liste d'entités documentée était fausse (`Aliases` n'existe pas, c'est
`Alias`) ;
- le MCP n'expose que 12 entités figées là où l'API en connaît 232.
---
## Lot 2 — Correctif de fond
### L2.1 — Résolution des entités via l'API Metadata
Accepter `entity_type` au nom d'entité (`Container`) ou au nom de jeu
(`Containers`), insensible à la casse, et émettre `Context.{TableName}`. Cache
identique aux autres (TTL partagé, invalidation au changement de profil).
Sur nom inconnu, échouer **avant tout appel réseau**, avec un message
actionnable :
> « Item » n'existe pas dans le modèle Reading. Proches : ItemGroup, StockItem.
> 232 entités disponibles — utilisez `get_entity_metadata` pour la liste.
Supprime la cause des 500 et débloque 232 entités au lieu de 12.
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.2 — Rejeter les paramètres inconnus
@@ -114,14 +73,6 @@ diagnostic exact, invisible depuis les outils comme depuis le smoke test.
Faire remonter `error.response.data` dans le message, comme L1.1 l'a fait pour
les outils. Même contrainte : ne jamais logguer les credentials.
### L3.3 — Documentation
- DECISIONS.md : **D21** la règle `TableName` (D22, le routage par table
explicite, a été livrée avec le lot 1).
- CLAUDE.md : corriger la liste d'entités (`Aliases``Alias`) et renvoyer vers
`get_entity_metadata` comme source de vérité.
- `wms://query-examples` : un exemple singulier/pluriel commenté.
---
## Lot 4 — Modèle de données et applications
@@ -186,9 +137,8 @@ applications).
`Application: "AGV"` qu'avec `Application: "EasyWMS"`. Le contexte de lecture est
**commun au tenant** : toutes les applications y déversent leurs entités.
Conséquence pour L2.1 : la table de résolution doit **agréger le Metadata de
toutes les applications** (`GET /Metadata/Entities?applicationName=…` par
application, 232 + 20 + 6 + …), et non se limiter à `EasyWMS`. Inutile en
Conséquence — traitée : la table de résolution (D21) **agrège le Metadata de
toutes les applications** déployées, et non le seul `EasyWMS`. Inutile en
revanche d'ajouter un paramètre `application` à `QueryExecute` : il ne changerait
rien.