diff --git a/STATUS.md b/STATUS.md
index a354e18..45fcfbb 100644
--- a/STATUS.md
+++ b/STATUS.md
@@ -30,9 +30,9 @@ Résumé de la table de suivi de ce fichier :
|---|---|---|
| manager-service | ✅ `dotnet build` et ✅ `dotnet test` **124/124** (2026-08-06) | La remise en route de la suite a révélé un **bug backend réel** : `BuildAuditEntries()` ajoutait un `AuditLog` au contexte *pendant* l'énumération du `ChangeTracker` → `InvalidOperationException: Collection was modified` sur toute écriture d'entité auditée (Section, Resource, Configuration, Device, User, Instance). Corrigé : énumération matérialisée, logs ajoutés après la boucle. Invisible jusque-là parce que les tests ne compilaient plus |
| manager-app | ✅ `flutter build web` | débloqué : `// @dart=2.18` manquant dans `manager_api_new/lib/api/onboarding_api.dart` (fichier ajouté à la main pour l'onboarding, sans l'annotation de version que porte `api.dart`) — **cassait les 3 apps Flutter d'un coup** |
-| mymuseum-visitapp | ✅ `flutter build apk` | débloqué par la même correction + typage explicite dans `guided_step_challenge.dart:83` |
+| mymuseum-visitapp | ❌ `flutter build apk` (**revérifié le 2026-08-11**) | Était ✅ le 2026-08-06, débloqué par la même correction + typage explicite dans `guided_step_challenge.dart:83`. **Casse maintenant côté Gradle**, pas côté Dart : `ndkVersion = "28.2.13676358"` réclamé dans `android/app/build.gradle`, avertissements KGP sur 11 plugins. Côté Dart il reste 4 erreurs, **toutes sur la branche Ray-Ban** (`kElevenLabsApiKey`/`kElevenLabsVoiceId` absents de `constants.dart`, jamais committés — voir §5bis), dans des fichiers hors du graphe de `main.dart`. Même famille que tablet-app : l'environnement Android a bougé |
| visitapp-web | ✅ `npm run build` | débloqué : helper `getGeoPointLatLng()` dans `src/lib/geo.ts`, les 7 erreurs venaient d'un `unknown` non narrowé. ⚠️ ce type d'erreur est **invisible en `next dev`** |
-| tablet-app | ❌ | échec Gradle sur `flutter_tools/gradle/build.gradle.kts` — **seul build encore cassé**, à investiguer, pas lié au client API |
+| tablet-app | ❓ | échec Gradle sur `flutter_tools/gradle/build.gradle.kts` — **seul build encore cassé** au 2026-08-06. ⚠️ **Peut-être corrigé depuis** : commit `5a6701d` « Drapeaux du migrateur Flutter (builtInKotlin, newDsl) ». À reconfirmer par un vrai build, pas par le log. **Le problème est purement Gradle** : une piste Dart (`ContentGeoPoint`) a été ouverte puis **écartée** le 2026-08-11, cf. §1sexies — ne pas la rouvrir |
**Leçon** : `flutter analyze` et `next dev` ne suffisent pas. Seuls `flutter build` / `npm run build` / `dotnet test` disent la vérité — d'où la nouvelle section §0 du plan de test.
@@ -308,6 +308,22 @@ Les lots 1 et 2 sont terminés. **Le lot 3 et le lot médias sont tous les deux
**Chemin critique** : A (assainir) → B (geler le schéma) → G (`MigrationController`) → H (tests) → **J (RGPD)** → I (bascule). C, D, D-bis, E, F se parallélisent.
+### Contrôle du code du 2026-08-11 (2e passe) — ce qui a bougé depuis la rédaction du plan
+
+> Tout vérifié dans le code, pas dans les docs. Deux points du lot A tombent, un point du lot A est différé, un nouveau suspect apparaît.
+
+| Point | Ce que disaient les docs (matin du 11/08) | Ce que dit le code (soir du 11/08) |
+|---|---|---|
+| **Lot A étape 1 — committer** | « 44 fichiers modifiés dont 9 non suivis, prérequis absolu » | ✅ **Fait.** **9 repos** propres et synchronisés avec leur remote — `DOCS/` en est un, ce qu'on oublie en énumérant les repos de code. Voir §4 |
+| **Lot A — rotation des secrets** | Verrou L1, **ouvre** le lot A | 📅 **Différée en fin de backlog**, juste avant I3, à la demande du 2026-08-11 — repos privés auto-hébergés. **Reste le verrou de I3**, ne disparaît pas. Voir §3 |
+| **Lot A — nettoyage `manager_api_new`** | « 14 fichiers modèle orphelins » | ✅ **Diagnostic fermé** : 139 `part` déclarés pour 153 fichiers, les 14 sont hors graphe de compilation → suppression sans effet possible sur un build. Plus `openApiTest.dart`, qui est le déclencheur de génération. Voir §3 |
+| **Lot A — build tablet-app** | « échec Gradle, seul build cassé » | ❓ commit `5a6701d` (« drapeaux du migrateur Flutter ») a peut-être réglé le Gradle, à reconfirmer par un vrai build. **Le problème reste purement Gradle** : une piste Dart a été ouverte puis écartée le même jour — `marker_view.dart:456` référence bien `ContentGeoPoint` (classe hors graphe), mais **la ligne est dans un bloc commenté**, comme sa jumelle de `mymuseum-visitapp:367`. `flutter analyze` sur les deux fichiers : zéro erreur. Ne pas rouvrir cette piste |
+| **DB3 — écran Guide IA** | « 🔨 front livré » | ✅ **Confirmé livré des deux côtés.** Onglets par boutons custom (`guide_ia_screen.dart:249-265`) — pas un `TabBar`, ce qui explique pourquoi le grep du plan concluait « aucun onglet » : la coquille existe bien. Backend : `AiController` `knowledge/{instanceId}:190` et `insights/{instanceId}:232`, `VisitorQuestionPurgeService.cs` présent |
+| **Onglet « Vocal » des stats** | « reste à faire » | ✅ Confirmé absent. `statsChannelVoice` n'est qu'un **libellé de canal** (`statistics_screen.dart:189`), pas un onglet |
+| **Lot B — les 4 changements de modèle** | « rien fait » | ✅ Confirmé, aucun n'a bougé : `SectionEvent.ParcoursIds:28`, `SectionMap.MapResourceId:25`, hardcode watermark `ResourceController.cs:265`, et `MeterZoneGPS` **sans aucun usage visiteur** (zéro occurrence dans `mymuseum-visitapp/lib` hors swagger, zéro dans `visitapp-web/src`) — le bug M3 est réel |
+| **Lot C1 — calculateur extrait** | « à faire » | ✅ Confirmé à faire : `StoragePath` n'apparaît que dans `ResourceController` et `Resource.cs`, aucun service |
+| **Lot D1** | « méthode existe, appelée nulle part » | ✅ Confirmé : hors des 13 sous-types, `GetReferencedResourceIds` n'apparaît que dans sa déclaration abstraite (`Section.cs:85`) et un test |
+
**RGPD reporté en fin de backlog le 2026-08-11** (lot J) — table d'agrégats de thèmes, job de regroupement, interrupteur de collecte par instance, mention affichée aux visiteurs, relecture juridique du §8 des CGU, vérification des conditions Google. C'est tenable **parce que** la porte « rien en prod avant la fin du backlog » tient : la journalisation ne tourne d'ici là que sur des bases de développement, aucun visiteur réel n'est concerné. Si un déploiement anticipé était décidé, ce lot redeviendrait bloquant.
**Le lot B n'existait nulle part** : tout changement de modèle encore ouvert (rename `MapResourceId`, arbitrage `ParcoursIds`, unification `QuestionType`, flag watermark) doit passer **avant** la réécriture de `BuildSection`, sinon on écrit le mapping deux fois — et après la bascule, c'est une migration de données sur la prod.
@@ -453,24 +469,38 @@ Le client ne manipule plus 9 booléens répartis sur 3 niveaux, mais répond à
→ Détail complet : **[security/audit-securite-manager-service.md](security/audit-securite-manager-service.md)** et **[security/audit-manager-app.md](security/audit-manager-app.md)** (audit du 2026-07-13/14)
### manager-service — reste à traiter (par priorité)
-- [ ] **Critique** — Secrets committés en clair dans Git (JWT signing key, clés API, connection strings, mot de passe MQTT, token Telegram) → rotation + variables d'environnement + purge historique Git + suppression `RELEASE/`
+- [ ] **Critique en exposition, différée en calendrier** — Secrets committés en clair dans Git (JWT signing key, clés API, connection strings, mot de passe MQTT, token Telegram) → rotation + variables d'environnement + purge historique Git + suppression `RELEASE/`
+ - 📅 **Déplacée en fin de backlog le 2026-08-11, à la demande.** Motif : les 6 repos sont **privés, sur un serveur Gitea auto-hébergé** — l'exposition réelle est celle d'un poste de dev, pas d'un dépôt public. La gravité ne change pas, la fenêtre d'urgence oui.
+ - ⚠️ **Ce que ça déplace dans le plan** : la rotation était le verrou L1 du lot A (« ne pas créer la prod avec les clés committées »). Elle reste ce verrou, mais **juste avant le lot I** au lieu d'ouvrir le lot A. La contrainte à ne pas perdre : **elle doit précéder I3** (compose/Traefik prod), sinon la prod naît avec les clés de l'historique et il faut rotationner deux fois.
+ - 🔒 **Condition de validité** : tenable tant que les repos restent privés et qu'aucun collaborateur externe n'est ajouté. Un repo rendu public, un fork, ou un CI tiers qui clone l'historique → la rotation remonte devant immédiatement.
- [ ] **Haute** — `EnableSensitiveDataLogging` actif en prod ; services Mongo legacy en singleton à corriger ; `ValueComparer` manquant sur les JSONB ; ~~`AssistantService` `new HttpClient()` en boucle~~ ✅ corrigé le 2026-08-07 (`IHttpClientFactory`, 4 occurrences)
- [ ] **Moyenne** — JWT sans expiration forcée, clés API en clair + comparaison non constant-time, bootstrap PIN sans rate limiting, exceptions internes exposées, backdoor `#if DEBUG`, double `SaveChangesAsync` audit (⚠️ vérifier après le fix du 2026-07-15 sur `SaveChanges`/`SaveChangesAsync` — peut être partiellement résolu), `SectionFactory` dupliqué, tests EF InMemory peu représentatifs
- [ ] **Basse** — conventions REST hétérogènes, `PasswordUtils` avec RNG non crypto, code mort (MQTT, CORS AllowAll), CORS en dur, ordre middleware
### manager-app — reste à traiter (par priorité)
- [ ] **Critique** — Client généré désynchronisé (`manager_api_new/`) : 14 fichiers modèle orphelins → `flutter analyze` inexploitable (183/200 erreurs de bruit)
+ - **Caractérisé précisément le 2026-08-11.** `lib/api.dart` déclare **139 `part`** pour **153 fichiers** dans `lib/model/`. Les 14 restants portent bien `part of openapi.api;` mais **ne sont déclarés `part` par personne** — en Dart, un fichier `part` non listé par sa bibliothèque est **hors du graphe de compilation**. D'où l'asymétrie qui a coûté du temps : l'analyzer les lit (il parcourt tout `lib/`), le compilateur ne les voit jamais. **Les supprimer ne peut pas changer un build.**
+ - Les 14 : `agenda_event_stat_dto`, `app_configuration_link_dto_application_instance`, `content_dto_resource`, `content_geo_point`, `day_stat_dto`, `game_stat_dto`, `level_dto`, `map_dto_map_provider`, `map_dto_map_type`, `map_dto_map_type_mapbox`, `poi_stat_dto`, `quiz_stat_dto`, `section_stat_dto`, `user`.
+ - **Fausse alerte levée le 2026-08-11, à ne pas rouvrir** : `ContentGeoPoint` (un des 14) *semble* référencé par du code vivant — `tablet-app/lib/Screens/Map/marker_view.dart:456` et `mymuseum-visitapp/lib/Screens/Sections/Map/marker_view.dart:367`, les deux apps dépendant de `manager_api_new` par `path:`. **Les deux lignes sont dans un bloc commenté** (`/*` ouvert respectivement en 418 et 329) : du code mort, invisible pour le compilateur *et* pour l'analyzer. Vérifié par comptage de délimiteurs et confirmé par `flutter analyze` sur les deux fichiers — zéro erreur. **Aucun des 14 n'a de référence vivante.**
+ - 🔒 **Les déclencheurs de génération partent avec eux, et pour une autre raison** : ce n'est pas du modèle mort, c'est le moyen de régénérer (annotation `@Openapi` + `build_runner`). Importés nulle part. Les supprimer ne retire aucun code exécuté — ça **verrouille la règle « `manager_api_new` s'édite à la main »** : tant qu'ils sont là, un `flutter pub run build_runner build` lancé par réflexe régénère le client et écrase les éditions manuelles (`onboarding_api.dart`, le câblage d'`AIApi`, le mapping `isGood` → `isCorrect`).
+ - ⚠️ **Ils étaient trois, pas un — trouvé le 2026-08-11.** La règle n'était verrouillée que dans manager-app :
+ - `manager-app/lib/api/openApiTest.dart` (dernier run daté du 2026-05-07)
+ - `mymuseum-visitapp/lib/api/openApiTest.dart` — **le plus dangereux** : il génère depuis **son propre `lib/api/swagger.yaml`** vers un `manager_api_new` local, ce qui aurait créé un second client divergent dans un repo qui consomme celui de manager-app par `path:`. Il portait en plus une des 5 erreurs Dart du repo
+ - `tablet-app/lib/api/openApi.dart` — même configuration (nom de fichier différent, d'où le fait qu'il ait échappé aux recherches précédentes sur `openApiTest`)
+ - plus un résidu `tablet-app/manager_api_new/` ne contenant qu'un `pubspec.lock`, non suivi par git, daté d'avril — une génération avortée
+ Les trois sont supprimés. **Contrôle de non-régression du verrou** : `grep -rl "@Openapi" */lib` ne doit renvoyer aucun fichier.
- [ ] **Haute** — Duplication du shell de dialog (15 occurrences), composants quasi-copiés (translation containers), méthodes `build()` monolithiques (440-640 lignes), i18n contournée (~100+ strings en dur)
- [ ] **Moyenne** — Clé AES en dur + IV fixe (chiffrement de session inutile), erreurs API avalées silencieusement (`catch (_) {}`), `_localPath` cassé, fichiers morts, TODO visibles à l'écran en prod, dépendances pubspec inutilisées
- [ ] **Basse** — façades API nullable jamais renullifiées, 58 `print()` de debug, credentials de test en dur, nommage non conforme Dart, `test/widget_test.dart` cassé (seul test du projet, ne compile pas)
-**Prochaine chose à faire si tu as 1h** : la rotation des secrets Git (Critique manager-service) — c'est le seul point de cette liste qui est une vraie urgence sécurité, le reste est de la dette gérable.
+**Prochaine chose à faire si tu as 1h** : ~~la rotation des secrets Git~~ → **le nettoyage de `manager_api_new`** (Critique manager-app). La rotation des secrets a été déplacée en fin de backlog le 2026-08-11 (repos privés auto-hébergés, cf. ci-dessus) ; le nettoyage du client, lui, est une demi-heure sans risque de build et il rend `flutter analyze` utilisable pour tout le lot design.
---
## 4. Infrastructure & Ops
-- [ ] ⚠️ **Travail non committé — largement résorbé, revérifié le 2026-08-11.** L'alerte du 2026-08-09 (« rien depuis le 17/07 », 75 + 40 + 14 + 4 fichiers) est **périmée** : les quatre repos ont un commit du **2026-08-09**. Reste en working tree le travail du 10-11/08 — `manager-service` ~41 fichiers (lot 3 RAG, `IngestionService`, colonnes médias, endpoint `knowledge`), `manager-app` (socle visuel, écran Guide IA 2 onglets), `myinfomate-landing` 7, et un commit non poussé sur `visitapp-web`. Reste à committer, mais ce n'est plus trois semaines sans filet
+- [x] ✅ **Travail non committé — résorbé. Revérifié le 2026-08-11 (2e passe) : plus rien en attente.** Les **9 repos** (DOCS compris) sont propres (`git status --porcelain` vide partout) **et à jour avec leur remote** (aucun `ahead`/`behind`). L'alerte du 2026-08-09 et sa révision du matin du 11/08 (« ~41 fichiers en working tree dont 9 non suivis ») sont toutes deux **périmées** : le lot 3 RAG est dans `18e4240`, le socle visuel + Guide IA dans `eb8e849`. **L'étape 1 du lot A est terminée** — ne pas la re-planifier
+ - Derniers commits par repo : `manager-service` `18e4240` (RAG : pipeline d'ingestion, endpoints du guide IA, journalisation RGPD) · `manager-app` `eb8e849` (socle visuel et écran Guide IA à deux onglets) · `visitapp-web` `473fc3a` · `mymuseum-visitapp` `af44927` · `tablet-app` `5a6701d` (drapeaux du migrateur Flutter) · `myinfomate-landing` `d91cf7f` · `unov-landing` `cfa70c4` · `OpenGlasses` `1d887d7`
- Rappel de l'état des branches : `manager-service` → `MyInfoMate_3.0`, `manager-app` → `Interface-refacto`, `mymuseum-visitapp` → `Meta-Rayban-Test` (23 commits d'avance sur `master`, voir §5bis), `tablet-app` → `AI-Assistant-test`, `visitapp-web` et les deux landings → `master`
- [ ] **pg_dump quotidien** pour `manager-service` (Postgres `my_info_mate`), en complément du snapshot OVH — voir mémoire `project_pgdump_todo`, pas encore fait au 2026-07-15. ⚠️ **Devient bloquant au moment de la bascule** : c'est le point 18 du [§1quinquies](#1quinquies-la-bascule-elle-même--mongo--postgres-en-prod-ajouté-le-2026-08-09), le seul filet du jour J
- ⛔ **Deuxième chose qu'il débloque** : le job `visit-events-purge` (purge des stats au-delà de 13 mois) est codé et enregistré mais **volontairement inactif** — il ne supprimera rien tant que `Stats:RetentionDays` n'est pas défini. Ne l'activer (`Stats__RetentionDays=395`) qu'une fois ce pg_dump en place
@@ -529,6 +559,8 @@ Pas « le SDK est en preview » — la liste est plus concrète :
- **TTS = ElevenLabs, facturé au caractère.** C'est le seul poste qui peut casser la marge d'un add-on à 20-30€/mois : un audioguide vocal génère du volume continu, contrairement au chat texte. `gemini_tts_engine.dart` existe déjà — **basculer dessus avant de vendre l'add-on**.
- **Wake word de prod non réglé** : `porcupine_flutter` est commenté dans `pubspec.yaml` (payant), l'implémentation courante s'appuie sur `speech_to_text` / openWakeWord.
- **Branche jamais mergée** dans `master`.
+- **Le POC ne compile plus en l'état — relevé le 2026-08-11.** `flutter analyze lib` sur `mymuseum-visitapp` remonte **4 erreurs**, toutes le même manque : `kElevenLabsApiKey` et `kElevenLabsVoiceId` sont **absents de `constants.dart`** alors que `glasses_qr_scanner_service.dart:110-111` et `wake_word_service.dart:133-134` les utilisent et importent bien `constants.dart`. La doc de `glasses_tts_service.dart:31-32` confirme l'intention (« typiquement `kElevenLabsApiKey` de `constants.dart` »). Ces deux constantes sont des **secrets qui n'ont jamais été committés** — le POC tournait avec un `constants.dart` local. Conséquence pratique : **« démontrable » suppose de les remettre**, ce n'est pas un `git checkout` qui suffit. À traiter avec la bascule TTS → Gemini ci-dessus, qui les rend inutiles.
+- ⚠️ **`flutter build apk` ne passe plus non plus**, pour une raison distincte et non liée au Dart : Gradle s'arrête sur `Gradle build failed to produce an .apk file`, avec une demande de `ndkVersion = "28.2.13676358"` dans `android/app/build.gradle` et des avertissements KGP sur 11 plugins. Le §1bis le donnait ✅ au 2026-08-06 : **c'est l'environnement Android qui a bougé, pas le code.** Même famille de problème que le build `tablet-app` du lot A.
### Ce que ça change côté commercial
diff --git a/kanban.html b/kanban.html
index 612b4a9..abc418e 100644
--- a/kanban.html
+++ b/kanban.html
@@ -454,13 +454,13 @@
- 5Urgent
+ 4Urgent
5Migration v3
7Bugs ouverts
6À tester
23Planifié
- 10Bascule prod
- 19Fait récemment
+ 11Bascule prod
+ 20Fait récemment
@@ -486,24 +486,9 @@
- Urgent
5
+ Urgent
4
-
- tous les reposRevérifié 11/08
- Travail non committé — largement résorbé
- L'alerte du 09/08 (« rien depuis le 17/07 », 75 + 40 + 14 + 4 fichiers) est périmée : les quatre repos ont un commit du 09/08. Reste en working tree le travail du 10-11/08 — manager-service ~41 fichiers (lot 3 RAG, IngestionService, colonnes médias, endpoint knowledge), manager-app (socle visuel, écran Guide IA), myinfomate-landing 7, plus un commit non poussé sur visitapp-web.
- Reste à committer, mais ce n'est plus trois semaines sans filet.
- STATUS.md §4 — Infrastructure & Ops
-
-
-
- manager-serviceSécurité
- Rotation des secrets committés en clair
- Clé de signature JWT, clés API Gemini et OpenWeather, connection strings prod, mot de passe MQTT, token Telegram. Le dossier RELEASE/ republie d'anciens secrets.
- security/audit-securite-manager-service.md
-
-
infraSécurité
Port PostgreSQL exposé publiquement
@@ -511,18 +496,31 @@
todo-features.md — Sécurité réseau
+
+ mymuseum-visitappBuild — nouveau 11/08
+ mymuseum-visitapp ne compile plus non plus
+ Le §1bis le donnait ✅ au 06/08. Revérifié le 11/08 : flutter build apk échoue côté Gradle — ndkVersion = "28.2.13676358" réclamé dans android/app/build.gradle, avertissements KGP sur 11 plugins. Ce n'est pas le Dart : le code applicatif analyse proprement.
+ Même famille que tablet-app : l'environnement Android a bougé sous les deux repos, le code n'a pas changé. Les traiter ensemble plutôt qu'un par un — c'est une seule migration Gradle/NDK, pas deux bugs.
+ Les 4 erreurs Dart restantes sont toutes sur la branche Ray-Ban et hors du graphe de main.dart : kElevenLabsApiKey et kElevenLabsVoiceId absents de constants.dart, jamais committés parce que ce sont des secrets. Le POC « démontrable » suppose donc de les remettre — voir §5bis.
+ STATUS.md §1bis · §5bis
+
+
tablet-appBuild
tablet-app ne compile pas
- Échec Gradle sur flutter_tools/gradle/build.gradle.kts. Seul build encore cassé des cinq. Le dernier APK date d'avril.
- parity-manager-visitapp.md §6 — B3
+ Échec Gradle sur flutter_tools/gradle/build.gradle.kts. Seul build encore cassé des cinq. Le dernier APK date d'avril. Peut-être déjà réglé par le commit 5a6701d (« drapeaux du migrateur Flutter ») — à reconfirmer par un vrai build, pas par le log.
+ Piste écartée le 11/08, à ne pas rouvrir : marker_view.dart:456 référence ContentGeoPoint, une classe absente de tout graphe de compilation — de quoi croire à un second défaut, côté Dart cette fois. Mais la ligne est dans un bloc commenté (/* ouvert en 418), comme sa jumelle de mymuseum-visitapp:367 (/* en 329). flutter analyze sur les deux fichiers : zéro erreur. Le problème de tablet-app est purement Gradle.
+ parity-manager-visitapp.md §6 — B3 · STATUS.md §1bis
manager_api_newDette
- Client généré désynchronisé
- Des fichiers modèle orphelins déclarent part of sans être inclus. Mesuré le 09/08 : 68 erreurs, quasi toutes de là (+ lib/api/openApiTest.dart) — moins que les ~183 relevées en juillet, mais flutter analyze global reste inexploitable comme feu vert : filtrer sur le dossier travaillé. flutter build web passe malgré elles, ces fichiers n'étant pas dans le graphe de compilation.
- security/audit-manager-app.md
+ Client généré désynchronisé — diagnostic fermé le 11/08
+ Le compte exact : api.dart déclare 139 part pour 153 fichiers dans lib/model/. Les 14 restants portent bien part of openapi.api; mais ne sont déclarés part par personne. En Dart, un fichier part non listé par sa bibliothèque est hors du graphe de compilation — l'analyzer le lit puisqu'il parcourt tout lib/, le compilateur ne le voit jamais. Toute l'asymétrie qui a coûté du temps est là, et avec elle la garantie : supprimer ces fichiers ne peut pas changer un résultat de build.
+ Les déclencheurs de génération partent avec eux, pour une autre raison : ce n'est pas du modèle mort, c'est le moyen de régénérer (annotation @Openapi + build_runner). Les supprimer ne retire aucun code exécuté — ça verrouille la règle « ce client s'édite à la main » : tant qu'ils sont là, un build_runner build lancé par réflexe écrase les éditions manuelles, dont onboarding_api.dart, le câblage d'AIApi et le mapping isGood → isCorrect.
+ ⚠️ Ils étaient trois, pas un. Le verrou ne tenait que dans manager-app : mymuseum-visitapp/lib/api/openApiTest.dart générait depuis son propre swagger vers un manager_api_new local — un second client divergent dans un repo qui consomme celui de manager-app par path: — et tablet-app/lib/api/openApi.dart faisait de même sous un autre nom de fichier, ce qui lui avait permis d'échapper aux recherches sur « openApiTest ». Les trois sont supprimés. Contrôle de non-régression : grep -rl "@Openapi" */lib doit rester vide.
+ Aucun des 14 n'a de référence vivante — vérifié. content_geo_point en avait l'air (tablet-app et mymuseum-visitapp), mais les deux usages sont dans des blocs commentés : voir la carte tablet-app.
+ security/audit-manager-app.md · STATUS.md §3
@@ -859,9 +857,18 @@
- Bascule prod
10
+ Bascule prod
11
+
+ étape 0Sécurité — avant l'étape 16
+ Rotation des secrets committés en clair
+ Clé de signature JWT, clés API Gemini et OpenWeather, connection strings prod, mot de passe MQTT, token Telegram. Le dossier RELEASE/ republie d'anciens secrets.
+ Déplacée depuis « Urgent » le 11/08, à la demande : les 6 repos sont privés, sur un Gitea auto-hébergé — l'exposition réelle est celle d'un poste de dev, pas d'un dépôt public. La gravité ne bouge pas, la fenêtre d'urgence oui.
+ ⚠️ Ce qui ne se négocie pas : elle doit précéder la création de l'environnement prod (étape 16), sinon la prod naît avec les clés de l'historique et il faut rotationner deux fois. Et comme le test d'onboarding exige app.myinfomate.be déployé, ça veut dire avant la fin du lot de tests, pas au tout dernier moment. Elle remonte en « Urgent » immédiatement si un repo passe public, gagne un collaborateur externe, ou est cloné par un CI tiers.
+ security/audit-securite-manager-service.md · v1-plan.md L1, I0
+
+
MigrationControllerSilencieux
Instance : 4 champs migrés sur ~35
@@ -939,9 +946,14 @@
Fait récemment
- Seize chantiers clos entre le 5 et le 10 août 2026.
+ Vingt chantiers clos entre le 5 et le 11 août 2026.
+
+ Plus rien sur un seul disque — les 8 repos sont propres
+ La carte la plus ancienne de la colonne « Urgent » se referme. L'alerte du 09/08 (« rien depuis le 17/07 », 75 + 40 + 14 + 4 fichiers) avait déjà été révisée le matin du 11/08 en « ~41 fichiers dont 9 non suivis » ; les deux versions sont maintenant périmées. Vérifié au git status --porcelain sur les huit repos : vide partout, et aucun ahead/behind face au remote. Le lot 3 RAG est dans 18e4240, le socle visuel et l'écran Guide IA dans eb8e849. Ce qui rendait le point urgent — neuf fichiers non suivis qui n'existaient nulle part ailleurs et disparaissaient au premier git checkout — n'existe plus. À ne pas re-planifier : c'était l'étape 1 du lot A.
+
+
Les maquettes sortent du compte Claude et entrent dans le repo
Cause diagnostiquée d'un défaut qui se répétait : les trois maquettes vivaient dans des artifacts d'un autre compte, illisibles depuis la machine de dev — chaque session redessinait. D'où un écran Guide IA « livré » à la moitié de sa spec et des stats d'assistant à zéro. Le HTML est rapatrié dans claude design/, JS interactif compris. Même découpage que ce tableau : contenu dans le repo, diffusion par artifact. Constat en ouvrant les fichiers : Guide IA et Statistiques déclarent des tokens rigoureusement identiques — c'était déjà un design system, jamais porté en Dart — et --brand #264863 est kPrimaryColor.
diff --git a/v1-plan.md b/v1-plan.md
index c295b34..0579043 100644
--- a/v1-plan.md
+++ b/v1-plan.md
@@ -30,7 +30,7 @@ C'est la partie qui manque partout ailleurs. Neuf liens réels, dont quatre impo
| # | Lien | Pourquoi |
|---|---|---|
-| L1 | **Rotation des secrets → création de l'environnement prod** (point 16 du §1quinquies) | Écrit noir sur blanc au §1quinquies : « ne pas créer la prod avec les clés committées ». Créer la prod d'abord, c'est rotationner deux fois |
+| L1 | **Rotation des secrets → création de l'environnement prod** (point 16 du §1quinquies) | Écrit noir sur blanc au §1quinquies : « ne pas créer la prod avec les clés committées ». Créer la prod d'abord, c'est rotationner deux fois. **⚠️ Modifié le 2026-08-11 : la rotation quitte le lot A pour le lot I (I0), mais le lien reste entier.** Ce n'est pas un assouplissement du lien, c'est un déplacement des deux bouts : les 6 repos sont privés sur un Gitea auto-hébergé, donc l'exposition ne justifie pas d'ouvrir le backlog avec elle. **La rotation doit toujours précéder I3.** Elle redevient urgente si un repo passe public, gagne un collaborateur externe, ou est cloné par un CI tiers |
| L2 | **Gel du schéma → réécriture de `MigrationController`** | `BuildSection` doit écrire dans le schéma **final**. Tout renommage ou unification de colonne fait après oblige à repasser dans les 13 branches du mapping. Voir §2 lot B |
| L3 | **`pg_dump` → bascule (point 18)** *et* **→ activation de `visit-events-purge`** | Un seul item débloque deux choses : le filet du jour J, et le job de purge des stats volontairement inactif tant que `Stats:RetentionDays` n'est pas défini |
| L4 | **RGPD → mise en service de `VisitorQuestion`** — **repoussé en fin de backlog le 2026-08-11 (lot J)** | Ce lien reste vrai, mais il ne contraint plus l'ordre : **rien ne part en prod avant que tout le backlog soit terminé** (§1quater de STATUS.md). Le lot J étant le dernier avant la bascule, le volet RGPD est en place avant la première question de visiteur réelle — la journalisation ne tourne d'ici là que sur des bases de développement. **La condition tient tant que cette porte tient** : si un déploiement anticipé était décidé, le lot J redeviendrait bloquant |
@@ -65,19 +65,25 @@ C'est la partie qui manque partout ailleurs. Neuf liens réels, dont quatre impo
Neuf lots. Le chemin critique passe par A → B → G → H ; les lots C à F sont parallélisables mais tous obligatoires avant H.
-### Lot A — Sauver et assainir (½ à 1 jour)
+### Lot A — Sauver et assainir (½ jour) — **révisé le 2026-08-11**
Rien de créatif, tout est un verrou pour la suite.
| Quoi | Où | Lien |
|---|---|---|
-| Committer le lot 3 RAG du 10/08 | `manager-service` (41 fichiers), `manager-app` (2), `tablet-app` (4), `myinfomate-landing` (7) ; pousser le commit d'avance de `visitapp-web` | — |
-| **Rotation des secrets** : JWT signing key, clés Gemini/OpenWeather, connection strings, mot de passe MQTT, token Telegram → variables d'environnement, purge de l'historique Git, suppression de `RELEASE/` | `manager-service` | **L1** — verrou du lot H |
-| Nettoyer `manager_api_new` : supprimer les 14 fichiers modèle orphelins + `lib/api/openApiTest.dart` | `manager-app` | **L8** — rend `flutter analyze` exploitable pour les lots D, E, F |
-| Réparer le build `tablet-app` (échec Gradle sur `flutter_tools/gradle/build.gradle.kts`) | `tablet-app` | Porte du test-plan §0 — les 5 commandes ne peuvent pas toutes passer sans lui |
-| Sécurité rapide : `EnableSensitiveDataLogging` coupé en prod, backdoor `#if DEBUG` retirée, exceptions internes plus exposées | `manager-service` | À faire avant que la prod existe, pas après |
+| ~~Committer le lot 3 RAG du 10/08~~ | — | ✅ **Fait le 2026-08-11.** Les **9 repos** sont propres et synchronisés avec leur remote. `manager-service` `18e4240`, `manager-app` `eb8e849`. ⚠️ **`DOCS/` est lui-même un repo git** (branche `main`) — facile à oublier quand on énumère les repos de code, et c'est là que vivent ce plan, STATUS.md et le kanban |
+| ~~**Rotation des secrets**~~ | `manager-service` | 📅 **Déplacée au lot I (I0)** le 2026-08-11 — repos privés sur Gitea auto-hébergé. **L1 tient : elle précède toujours I3.** Voir la note de L1 pour les conditions qui la font remonter |
+| Nettoyer `manager_api_new` : supprimer les 14 fichiers modèle orphelins + `lib/api/openApiTest.dart` | `manager-app` | **L8** — rend `flutter analyze` exploitable pour les lots D, E, F. **Diagnostic fermé le 2026-08-11**, détail ci-dessous |
+| Réparer le build `tablet-app` | `tablet-app` | Porte du test-plan §0. **Un seul défaut, purement Gradle** (`flutter_tools/gradle/build.gradle.kts`) — peut-être déjà réglé par `5a6701d`, à reconfirmer par un vrai build. Une piste Dart a été ouverte puis **écartée** le 2026-08-11 : `marker_view.dart:456` référence `ContentGeoPoint`, classe hors graphe, mais **la ligne est dans un bloc commenté** (`/*` ouvert en 418), comme sa jumelle de `mymuseum-visitapp:367` (`/*` en 329). `flutter analyze` sur les deux fichiers : zéro erreur. Ne pas rouvrir |
+| Sécurité rapide : `EnableSensitiveDataLogging` coupé en prod (`Startup.cs:248`), backdoor `#if DEBUG` retirée, exceptions internes plus exposées | `manager-service` | À faire avant que la prod existe, pas après |
-> À ne pas régénérer : `manager_api_new` s'édite à la main (règle du projet). Le nettoyage supprime des fichiers orphelins, il ne relance pas la génération.
+**Pourquoi le nettoyage de `manager_api_new` est sans risque de build** — vérifié le 2026-08-11, à ne pas re-douter :
+
+`lib/api.dart` déclare **139 `part`** pour **153 fichiers** dans `lib/model/`. Les 14 restants portent `part of openapi.api;` mais **ne sont déclarés `part` par personne**. En Dart, un fichier `part` non listé par sa bibliothèque est **hors du graphe de compilation** : l'analyzer le lit (il parcourt tout `lib/`), le compilateur ne le voit jamais. C'est toute l'explication des 68 erreurs de bruit — et la garantie que **supprimer ces fichiers ne peut pas changer un résultat de build.**
+
+`lib/api/openApiTest.dart` part avec eux pour une raison différente : ce n'est pas du modèle mort, c'est **le déclencheur de la génération** (annotation `@Openapi` + `build_runner`, dernier run daté du 2026-05-07), importé nulle part. Le supprimer ne retire aucun code exécuté — ça **verrouille la règle du projet** : tant qu'il est là, un `flutter pub run build_runner build` lancé par réflexe régénère le client et écrase les éditions manuelles (`onboarding_api.dart`, le câblage d'`AIApi`, le mapping `isGood` → `isCorrect`).
+
+> À ne pas régénérer : `manager_api_new` s'édite à la main (règle du projet). Le nettoyage supprime des fichiers orphelins **et le moyen de régénérer** ; il ne relance rien.
### Lot B — Geler le schéma (2 à 3 jours) — le point d'articulation
@@ -218,6 +224,7 @@ Les CGU §8 ont été réécrites le 2026-08-11 (`cgu-myinfomate.md`) et le text
| # | Quoi | Lien |
|---|---|---|
+| **I0** | **Rotation des secrets** : JWT signing key, clés Gemini/OpenWeather, connection strings, mot de passe MQTT, token Telegram → variables d'environnement, purge de l'historique Git, suppression de `RELEASE/` | **L1** — déplacée du lot A le 2026-08-11. **Doit précéder I3** : la prod ne doit pas naître avec les clés de l'historique, sinon il faut rotationner deux fois. C'est le premier geste du lot I, pas une option |
| I1 | **`pg_dump` quotidien** en cron, en complément du snapshot OVH | **L3** — puis activer `Stats__RetentionDays=395` et vérifier que `visit-events-purge` ne supprime rien |
| I2 | Backup Mongo automatique en cron (dump + `docker cp` vers l'hôte) | Filet du rollback |
| I3 | **Un seul chantier compose/Traefik** : `Dockerfile.postgres` épinglé par digest, **port 5432 fermé**, entrée `app.myinfomate.be` + Dockerfile `visitapp-web` | **L7** — trois cartes, un fichier. **L1** : après la rotation des secrets |
@@ -247,13 +254,13 @@ A (½-1j) ──► B (2-3j) ──► G (3-4j) ──► H (1 sem.) ──► I
├──► E
└──► F
- J (RGPD) ──► I ← dernier avant la bascule
+ J (RGPD) ──► I0 (secrets) ──► I3 ──► reste de I
```
- **Chemin critique : A → B → G → H → I.** Tout le reste s'y greffe.
- **C, D, D-bis, E, F sont parallélisables** entre eux, mais **C1 doit précéder G** (L5) et **B doit précéder G** (L2).
- **DB3 doit précéder le job de thèmes du lot F** (L16) : c'est le seul endroit du plan où le design commande le backend.
-- **I3 dépend de A** (rotation des secrets, L1) et **H4 dépend de I3** (L12) : c'est la seule boucle du graphe. Elle se résout en déployant `app.myinfomate.be` **avant** la fin de H, ce qui est possible dès que A est fini — le web ne dépend pas de la bascule Postgres.
+- **La boucle du graphe a disparu le 2026-08-11.** Elle venait de : I3 dépend de la rotation des secrets (dans le lot A), et H4 dépend de I3 (L12). En déplaçant la rotation en **I0**, la contrainte devient linéaire — `I0 → I3 → H4` — et il n'y a plus de cycle à contourner. **Contrepartie à ne pas rater** : H4 (test d'onboarding) exige `app.myinfomate.be` déployé, donc I3, donc I0. Concrètement, **la rotation des secrets doit être faite avant la fin du lot H**, pas au tout dernier moment. C'est le seul endroit où le report du 11/08 crée une échéance interne.
**Ordre de grandeur : 5 à 6 semaines**, dont ~1 semaine de tests, 3-4 jours sur `MigrationController` seul, 1,5 à 2 semaines sur le lot design et 2-3 jours sur le lot J (RGPD). Les deux arbitrages du lot B (`ParcoursIds`, `QuestionType`) et celui du lot D-bis (flux SectionParcours) sont les seuls points où le plan attend une décision plutôt qu'un développement.
@@ -286,11 +293,11 @@ Les plans détaillés de `v2/` ne se lisent qu'au moment d'attaquer le lot conce
**Trois pièges vérifiés en vrai, à ne pas re-découvrir :**
-- **`flutter analyze` global est inexploitable** (68 erreurs de fichiers modèle orphelins, hors graphe de compilation). Filtrer sur le dossier travaillé. Seuls `flutter build web`, `dotnet build`, `dotnet test` disent la vérité.
+- **`flutter analyze` global est inexploitable** (68 erreurs de fichiers modèle orphelins, hors graphe de compilation). Filtrer sur le dossier travaillé. Seuls `flutter build web`, `dotnet build`, `dotnet test` disent la vérité. **Cause exacte établie le 2026-08-11** : 139 `part` déclarés dans `api.dart` pour 153 fichiers dans `lib/model/` — cf. lot A. Le nettoyage du lot A supprime ce bruit.
- **La base locale peut avoir une migration de retard**, ce qui fait planter l'API dès le login sans que le compilateur ne dise rien.
- **Le fichier du kanban et la version publiée peuvent avoir divergé** — toujours `WebFetch` l'artifact et fusionner avant de republier, jamais `force`.
-⚠️ **Prérequis absolu avant de travailler depuis une autre machine ou un autre poste : committer.** Relevé le 2026-08-11 — `manager-service` a 44 fichiers modifiés dont **9 non suivis** (`IngestionService`, `SectionIndexingInterceptor`, `IVectorStoreService`, les DTO du guide…), `manager-app` 12 dont `visitor_questions_tab.dart`. Ces fichiers-là n'existent nulle part ailleurs et disparaissent au premier `git checkout`. C'est le lot A, étape 1.
+✅ **Le prérequis « committer avant tout » est levé.** L'alerte de ce matin (`manager-service` 44 fichiers dont 9 non suivis, `manager-app` 12) est **traitée** : revérifié le 2026-08-11, les **9 repos** (DOCS compris) sont propres et synchronisés avec leur remote. Rien n'est plus en attente sur un seul disque. Ne pas re-planifier cette étape.
---