feat(admin): application d'administration (auth, métriques, monitoring, tri des corrections) #15

Merged
kyuno merged 7 commits from feat/admin-tech-steps into main 2026-08-29 09:43:07 +02:00
Owner

Bloc application d'administration regroupé en une seule PR (remplace la pile #7 / #8 / #13 / #14 / #15, désormais fermées).

Nouveau frontend apps/admin-web indépendant (Vite/React, port 5174 dev, image Docker nginx propre) + surface /admin/* dans apps/api (qui reste seul propriétaire du schéma Prisma). Contenu : 5 commits, branche feat/admin-tech-steps basée sur main.

1 — Auth (cf8ef26)

Table AdminUser isolée (aucune relation vers UserProfile), requireAdmin (cookie admin_session, secret ADMIN_JWT_SECRET dédié, échoue fermé si absent), /admin/auth/{login,logout,me}, create-admin.ts (1ᵉʳ admin hors-bande). CORS setupCore accepte string[]. Mocha admin-auth.test.ts.

2 — Scaffold apps/admin-web (8a6143d)

AdminApiClient / AdminAuthContext / RequireAdmin / AdminLayout (calqués sur apps/web), LoginPage, Dockerfile nginx + service docker-compose, i18n, tokens _theme.scss copiés. Cypress login.feature + admin-layout.cy.ts, job CI admin-web e2e.

3 — Métriques (b08081e)

Migration admin_metrics : AnalyticsEvent + WorkerHeartbeat + colonnes createdAt sur UserProfile/Recipe/Planning/PlanningItem. analytics.recordEvent() fire-and-forget instrumenté dans 6 services. GET /admin/metrics?days= + bucketByDay pur. DashboardPage (tuiles KPI + graphes recharts). Mocha + Cypress.

4 — Monitoring (57cb2b7)

POST /internal/tech-steps/heartbeat + recordWorkerHeartbeat — le worker LLM (sans surface HTTP) devient observable ; il ping au boot/tick/job. GET /admin/monitoring : sondes actives bornées (Postgres, API, intent-service /health, worker via heartbeat), statut up/degraded/down/unknown. MonitoringPage (poll 15 s). Mocha + Cypress.

5 — Tri des corrections + retrain (ed68e11)

/admin/tech-steps/* : suggestions groupées par technique + filtres, corrections brutes (incl. les suppressions correctedTechStepId:null invisibles ailleurs), PATCH d'une suggestion, GET /training-data-snippet (bloc à coller), POST /retrain (gate F1 runTechStepEvalSuite + backfillTechSteps + verrou process → 409 RETRAIN_ALREADY_RUNNING, nouveau ErrorCode 4023). CorrectionsPage (2 onglets + bandeau caveat « édition du .py + redémarrage intent-service restent manuels »). Mocha + Cypress.

Vérif

pnpm lint + pnpm -r build verts. Admin-web Cypress 13/13. Worker Mocha 6/6. bucketByDay pur 2/2.
⚠️ Les 4 suites Mocha API admin non exécutées dans la session (pas de Postgres:5433) — écrites, self-skip des cas dépendant des secrets ; ci.yml fournit ADMIN_JWT_SECRET. POST /retrain de la partie 5 a besoin de tech-step-intent-service démarré (comme les suites tech-step existantes).

specs/backend-architecture.md : section ## admin complète.

🤖 Generated with Claude Code

Bloc **application d'administration** regroupé en une seule PR (remplace la pile #7 / #8 / #13 / #14 / #15, désormais fermées). Nouveau frontend `apps/admin-web` **indépendant** (Vite/React, port 5174 dev, image Docker nginx propre) + surface `/admin/*` dans `apps/api` (qui reste seul propriétaire du schéma Prisma). Contenu : 5 commits, branche `feat/admin-tech-steps` basée sur `main`. ## 1 — Auth (`cf8ef26`) Table `AdminUser` **isolée** (aucune relation vers `UserProfile`), `requireAdmin` (cookie `admin_session`, secret `ADMIN_JWT_SECRET` dédié, échoue fermé si absent), `/admin/auth/{login,logout,me}`, `create-admin.ts` (1ᵉʳ admin hors-bande). CORS `setupCore` accepte `string[]`. Mocha `admin-auth.test.ts`. ## 2 — Scaffold `apps/admin-web` (`8a6143d`) `AdminApiClient` / `AdminAuthContext` / `RequireAdmin` / `AdminLayout` (calqués sur `apps/web`), `LoginPage`, Dockerfile nginx + service `docker-compose`, i18n, tokens `_theme.scss` copiés. Cypress `login.feature` + `admin-layout.cy.ts`, job CI `admin-web e2e`. ## 3 — Métriques (`b08081e`) Migration `admin_metrics` : `AnalyticsEvent` + `WorkerHeartbeat` + colonnes `createdAt` sur `UserProfile`/`Recipe`/`Planning`/`PlanningItem`. `analytics.recordEvent()` **fire-and-forget** instrumenté dans 6 services. `GET /admin/metrics?days=` + `bucketByDay` pur. `DashboardPage` (tuiles KPI + graphes recharts). Mocha + Cypress. ## 4 — Monitoring (`57cb2b7`) `POST /internal/tech-steps/heartbeat` + `recordWorkerHeartbeat` — le worker LLM (sans surface HTTP) devient observable ; il ping au boot/tick/job. `GET /admin/monitoring` : sondes actives bornées (Postgres, API, intent-service `/health`, worker via heartbeat), statut `up/degraded/down/unknown`. `MonitoringPage` (poll 15 s). Mocha + Cypress. ## 5 — Tri des corrections + retrain (`ed68e11`) `/admin/tech-steps/*` : suggestions groupées par technique + filtres, corrections brutes (incl. les suppressions `correctedTechStepId:null` invisibles ailleurs), `PATCH` d'une suggestion, `GET /training-data-snippet` (bloc à coller), `POST /retrain` (gate F1 `runTechStepEvalSuite` + `backfillTechSteps` + verrou process → `409 RETRAIN_ALREADY_RUNNING`, nouveau `ErrorCode` 4023). `CorrectionsPage` (2 onglets + bandeau caveat « édition du .py + redémarrage intent-service restent manuels »). Mocha + Cypress. ## Vérif `pnpm lint` + `pnpm -r build` verts. **Admin-web Cypress 13/13**. Worker Mocha 6/6. `bucketByDay` pur 2/2. ⚠️ Les 4 suites Mocha API admin non exécutées dans la session (pas de Postgres:5433) — écrites, self-skip des cas dépendant des secrets ; `ci.yml` fournit `ADMIN_JWT_SECRET`. `POST /retrain` de la partie 5 a besoin de `tech-step-intent-service` démarré (comme les suites tech-step existantes). `specs/backend-architecture.md` : section `## admin` complète. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
kyuno added 1 commit 2026-08-28 14:50:17 +02:00
feat(admin): tri des corrections + declenchement du gate F1/backfill
Some checks failed
CI / build (push) Has been cancelled
CI / e2e (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / intent-service-test (push) Has been cancelled
CI / test (push) Has been cancelled
ed68e1146f
PR 5 (derniere) du chantier admin. Remplace le duo CLI
list-pending-training-suggestions.ts / retrain-tech-steps.ts par une UI.

API (admin-tech-steps.service.ts, routes /admin/tech-steps/*, requireAdmin) :
- GET /suggestions : TechStepTrainingSuggestion filtrees, groupees par
  technique, enrichies du contexte de la correction source.
- GET /corrections : corrections brutes filtrables, incluant les
  suppressions correctedTechStepId:null invisibles ailleurs.
- PATCH /suggestions/:id : edite synonymes/phrases et/ou status.
- GET /training-data-snippet : bloc training_data.py a coller (lecture
  seule).
- POST /retrain : runTechStepEvalSuite() (gate F1 vs MIN_OVERALL_F1) puis
  si passe backfillTechSteps() + marquage applied/rejected. Verrou memoire
  -> 409 RETRAIN_ALREADY_RUNNING. Gate echoue -> 200 gatePassed:false.
  N'edite pas le .py ni ne redemarre l'intent-service (manuel).

Shared : nouveau ErrorCode RETRAIN_ALREADY_RUNNING (4023, + cle i18n
apps/web), schemas (list*/update*/retrain*/snippet), types
(TrainingSuggestion*/Correction*/RetrainResultView...).

Front : CorrectionsPage (onglets Suggestions / Corrections brutes,
bandeau caveat permanent, cartes editables + Appliquer/Rejeter, panneau
snippet, panneau gate F1). Logique pure corrections.ts. i18n
admin.corrections.*. AdminApiClient : 5 methodes.

Tests : Mocha admin-tech-steps.test.ts (401 partout, groupement+filtre,
PATCH 400/404/ok, corrections incluant removals, snippet, retrain shape +
409 concurrent) ; Cypress corrections.cy.ts (4 verts). Admin-web Cypress
13/13. specs/backend-architecture.md : section tri + retrain.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
kyuno changed title from feat(admin): tri des corrections + déclenchement du gate F1/backfill to feat(admin): application d'administration (auth, métriques, monitoring, tri des corrections) 2026-08-28 15:27:10 +02:00
kyuno changed target branch from feat/admin-monitoring to main 2026-08-28 15:27:11 +02:00
kyuno force-pushed feat/admin-tech-steps from ed68e1146f to 15dad91a43 2026-08-28 19:07:51 +02:00 Compare
kyuno force-pushed feat/admin-tech-steps from 15dad91a43 to 74b1657590 2026-08-28 23:00:19 +02:00 Compare
kyuno force-pushed feat/admin-tech-steps from 74b1657590 to fcaecb4e07 2026-08-28 23:37:35 +02:00 Compare
kyuno added 2 commits 2026-08-29 09:42:59 +02:00
feat(recipes): permet d'ajouter des ingredients hors-catalogue
Some checks failed
CI / lint (push) Successful in 1m46s
CI / build (push) Successful in 1m55s
CI / e2e (push) Successful in 8m37s
CI / intent-service-test (push) Successful in 17m3s
CI / test (push) Failing after 3h14m19s
16f593d5d0
Quand le catalogue seede ne couvre pas un ingredient, l'utilisateur pouvait
etre bloque (creation manuelle) ou perdre silencieusement la ligne (import).
Une ligne de recette accepte desormais `placeholderName` (texte libre) au
lieu de `ingredientId` : l'API cree une ligne `Ingredient` `isPlaceholder`
(cle `placeholder:<uuid>`, `displayName`, `createdById`) dans la transaction
de la recette, et emet `ingredient.placeholder_created`. Ces lignes sont
exclues de `GET /reference/ingredients` et de `ingredient-matcher`.

Front : bouton "Ajouter << ... >>" dans l'etat vide de `IngredientPicker`
(formulaire + import), badge "a completer" sur la ligne, helper
`ingredientLabel` applique partout ou un libelle d'ingredient est rendu.

Admin : `/admin/catalog/*` (+ page `apps/admin-web`) liste les placeholders
regroupes par nom normalise, "marquer traite" (`reviewedAt`) et purge des
orphelins. La promotion en vraie entree catalogue reste manuelle.

Migration `ingredient_placeholder` ecrite a la main (Postgres indisponible).
Suites Mocha DB-backed ecrites, non executees en session ; test pur
`normalizePlaceholderName` + Cypress admin-web/web verts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Merge pull request 'feat(recipes): ingrédients hors-catalogue (placeholders) + revue admin' (#16) from feat/off-catalog-ingredients into feat/admin-tech-steps
Some checks failed
CI / intent-service-test (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled
CI / e2e (push) Has been cancelled
f7aabd9dcc
Reviewed-on: #16
kyuno merged commit a33f641dc7 into main 2026-08-29 09:43:07 +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#15
No description provided.