fix(admin): isole l'API admin sous /admin/api pour éviter la collision avec les pages front #33

Merged
kyuno merged 1 commit from fix/admin-monitoring-spa-route-collision into main 2026-09-05 14:24:59 +02:00
Owner

Bug

Un F5 sur /admin/monitoring affichait le JSON brut de l'API au lieu de la page.

Cause

server.mountRouter("/admin", adminRouter) (app.ts) montait l'API admin exactement sous /admin — la même racine que les pages /admin/* d'apps/web, servies depuis la même origine/le même process en prod (image Docker unique, serveStaticFrontend). Express matche par chemin sans égard au header Accept : GET /admin/monitoring (route API) et la page du même nom étaient en conflit direct, et l'API gagnait systématiquement (montée avant le fallback SPA) — donc chaque F5 sur cette page recevait le JSON de l'API plutôt que index.html.

Seule /admin/monitoring collidait réellement aujourd'hui (le seul sous-routeur admin à répondre GET sur sa racine bare — vérifié pour /admin/metrics, /admin/catalog, /admin/tech-steps : aucune page front ne partage exactement leur chemin), mais le mécanisme touche potentiellement toute future route admin nommée comme sa page — d'où un correctif structurel plutôt qu'un renommage ponctuel de /admin/monitoring seul.

Correctif

L'API admin est montée sous /admin/api, jamais bare /admin. Toute la surface admin bouge en conséquence (auth/metrics/monitoring/tech-steps/catalog) ; les pages front (/admin/monitoring, /admin/catalogue, /admin/corrections...) sont inchangées — seul admin-client.ts change de base URL.

Mis à jour en cohérence : commentaires JSDoc citant les routes (apps/api + apps/web + packages/shared), specs/backend-architecture.md, specs/batch-cooking-modele.md, les intercepts Cypress (globs + un matcher regex qui avait échappé au premier passage de vérification), et les chemins supertest de la suite Mocha admin-*.test.ts.

Simplifie au passage admin-monitoring.cy.ts : le contournement resourceType ajouté dans #32 pour cette même collision n'a plus lieu d'être une fois les chemins distincts (retour à un intercept déclaratif simple) — le bug Cypress/Chrome qu'il avait mis au jour reste noté en commentaire pour référence future, indépendamment de ce correctif.

Vérification

  • pnpm lint : clean
  • Build api + web : clean
  • Suite e2e Cypress complète : 28/28 fichiers, 116/116 tests verts (dont les 16 tests admin-*)
  • Confirmé en direct : fetch("/admin/monitoring") renvoie maintenant text/html (la page), plus jamais du JSON
  • Suite Mocha apps/api non exécutable cette session (Postgres/Docker injoignable) — les ~40 chemins supertest ont été mis à jour mécaniquement en cohérence avec le nouveau mount point ; à faire tourner en CI ou à la prochaine session avec accès DB avant de considérer ce point définitivement clos.

🤖 Generated with Claude Code

## Bug Un F5 sur `/admin/monitoring` affichait le JSON brut de l'API au lieu de la page. ## Cause `server.mountRouter("/admin", adminRouter)` ([app.ts](apps/api/src/app.ts)) montait l'API admin exactement sous `/admin` — la même racine que les pages `/admin/*` d'apps/web, servies depuis la même origine/le même process en prod (image Docker unique, `serveStaticFrontend`). Express matche par chemin sans égard au header `Accept` : `GET /admin/monitoring` (route API) et la page du même nom étaient en conflit direct, et l'API gagnait systématiquement (montée avant le fallback SPA) — donc chaque F5 sur cette page recevait le JSON de l'API plutôt que `index.html`. Seule `/admin/monitoring` collidait réellement aujourd'hui (le seul sous-routeur admin à répondre `GET` sur sa racine bare — vérifié pour `/admin/metrics`, `/admin/catalog`, `/admin/tech-steps` : aucune page front ne partage exactement leur chemin), mais le mécanisme touche potentiellement toute future route admin nommée comme sa page — d'où un correctif structurel plutôt qu'un renommage ponctuel de `/admin/monitoring` seul. ## Correctif L'API admin est montée sous `/admin/api`, jamais bare `/admin`. Toute la surface admin bouge en conséquence (`auth`/`metrics`/`monitoring`/`tech-steps`/`catalog`) ; les pages front (`/admin/monitoring`, `/admin/catalogue`, `/admin/corrections`...) sont **inchangées** — seul [admin-client.ts](apps/web/src/api/admin-client.ts) change de base URL. Mis à jour en cohérence : commentaires JSDoc citant les routes (apps/api + apps/web + packages/shared), `specs/backend-architecture.md`, `specs/batch-cooking-modele.md`, les intercepts Cypress (globs + un matcher regex qui avait échappé au premier passage de vérification), et les chemins supertest de la suite Mocha `admin-*.test.ts`. Simplifie au passage `admin-monitoring.cy.ts` : le contournement `resourceType` ajouté dans #32 pour cette même collision n'a plus lieu d'être une fois les chemins distincts (retour à un intercept déclaratif simple) — le bug Cypress/Chrome qu'il avait mis au jour reste noté en commentaire pour référence future, indépendamment de ce correctif. ## Vérification - `pnpm lint` : clean - Build `api` + `web` : clean - Suite e2e Cypress complète : **28/28 fichiers, 116/116 tests verts** (dont les 16 tests `admin-*`) - Confirmé en direct : `fetch("/admin/monitoring")` renvoie maintenant `text/html` (la page), plus jamais du JSON - Suite Mocha `apps/api` **non exécutable cette session** (Postgres/Docker injoignable) — les ~40 chemins supertest ont été mis à jour mécaniquement en cohérence avec le nouveau mount point ; à faire tourner en CI ou à la prochaine session avec accès DB avant de considérer ce point définitivement clos. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
kyuno added 1 commit 2026-09-05 13:48:39 +02:00
fix(admin): isole l'API admin sous /admin/api pour éviter la collision avec les pages front
All checks were successful
CI / build (push) Successful in 2m53s
CI / lint (push) Successful in 2m55s
CI / intent-service-test (push) Successful in 5m6s
CI / e2e (push) Successful in 8m17s
CI / test (push) Successful in 15m19s
ba131bd8c8
Un rafraîchissement (F5) sur /admin/monitoring affichait le JSON brut de
l'API au lieu de la page — même chose à craindre pour tout futur /admin/*
GET sans segment supplémentaire.

Cause : `server.mountRouter("/admin", adminRouter)` (app.ts) montait
l'API admin exactement sous /admin, la même racine que les pages
/admin/* d'apps/web, servies depuis la même origine/le même process en
prod (image Docker unique). Express matche par chemin, sans égard au
Accept — `GET /admin/monitoring` (route API) et la page du même nom
étaient en conflit direct ; l'API gagnait systématiquement (montée
avant serveStaticFrontend), donc chaque F5 sur cette page recevait le
JSON de l'API plutôt que index.html.

Seule /admin/monitoring collidait réellement aujourd'hui (seul
sous-routeur admin à répondre GET sur sa racine bare) mais le
mécanisme touche toute future route admin nommée comme sa page — d'où
un correctif structurel plutôt qu'un renommage ponctuel.

Correctif : l'API admin est montée sous /admin/api (app.ts), jamais
bare /admin. Toute la surface admin bouge en conséquence
(auth/metrics/monitoring/tech-steps/catalog) ; les pages front
(/admin/monitoring, /admin/catalogue, /admin/corrections...) sont
inchangées, seul admin-client.ts change de base URL. Mis à jour en
cohérence : commentaires JSDoc citant les routes (apps/api + apps/web +
packages/shared), specs/backend-architecture.md,
specs/batch-cooking-modele.md, les intercepts Cypress (globs + un
matcher regex qui avait échappé au premier passage) et les chemins
supertest du suite Mocha admin-*.test.ts.

Simplifie au passage admin-monitoring.cy.ts : le contournement
resourceType ajouté en #32 pour cette même collision n'a plus lieu
d'être une fois les chemins distincts (retour à un intercept déclaratif
simple) — le bug Cypress/Chrome qu'il avait mis au jour reste noté en
commentaire pour référence future.

Vérifié : pnpm lint clean ; build api+web clean ; suite e2e complète
28/28 fichiers, 116/116 tests verts (dont les 16 tests admin-*).
Suite Mocha apps/api non exécutable cette session (Postgres/Docker
injoignable) — chemins mis à jour mécaniquement en cohérence avec le
nouveau mount point, à faire tourner en CI/à la prochaine session avec
accès DB.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
kyuno merged commit 71c409cf32 into main 2026-09-05 14:24:59 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: kyuno/batchCooking#33
No description provided.