Décisions tarifaires et requalification de deux écarts du lot G
Décisions consignées pour ne pas être re-tranchées : plans alignés sur la grille, add-on IA sur les plans sans IA, affectation des 4 clients existants, et les deux pièges qui vont avec (sémantique asymétrique du 0, rattrapage d'indexation non déclenché par un UPDATE en SQL). Requalification de deux écarts du lot G, vérifiés dans l'export Mongo : - (a) « BuildSection ne couvre que 11 types sur 13 » est une fausse alerte : les 327 sections de l'export ne contiennent que les types 0 à 10. SectionEvent et SectionParcours n'existaient pas dans Mongo, ils sont nés avec Postgres v3. Le default est un filet, pas un trou. - (c) « Instance : 4 champs migrés sur ~35 » n'est pas un oubli de mapping : la source ne contient que 4 champs. Les 31 autres sont à générer, dériver ou décider. Signalé sans le traiter : la FAQ de la landing appelle encore le plan à 179€ « Bundle » (41 occurrences, 4 langues) là où la grille dit Premium. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
005f5c1606
commit
c180230f49
39
v1-plan.md
39
v1-plan.md
@ -188,8 +188,8 @@ Les 8 écarts a→h du §1quinquies. Ne démarre qu'après les lots B et C1 (**L
|
|||||||
|
|
||||||
| Écart | Quoi | Attention |
|
| Écart | Quoi | Attention |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| c | `Instance` : 4 champs migrés sur ~35 | **Le plus dangereux : aucune erreur levée.** `PublicApiKey` null = les apps visiteur ne s'authentifient plus ; `WebSlug` null = visitapp-web injoignable ; `SubscriptionPlanId` null = quotas à 0, donc `AiTokensPerMonth = 0`, donc **rien ne s'indexe** et l'IA tourne sans compteur. Réutiliser `ApplyPlanQuotas` |
|
| c | `Instance` : 4 champs migrés sur ~35 — **requalifié le 2026-08-11 : ce n'est pas un oubli de mapping.** `OldInstance` et l'export réel ne contiennent que `_id`, `Name`, `DateCreation`, `PinCode`. Les 31 autres colonnes **n'existent pas dans la source** : elles sont nées avec Postgres v3. Il n'y a donc rien à mapper, il faut **générer, dériver ou décider**. `PublicApiKey` → générer · `WebSlug` → dériver du `Name` (`SlugHelper` existe) · `IsMobile`/`IsTablet`/`IsWeb` → dériver des `ApplicationInstance` réellement présentes · `SubscriptionPlanId` → décidé, voir ci-dessous | **Le plus dangereux : aucune erreur levée.** `PublicApiKey` null = les apps visiteur ne s'authentifient plus ; `WebSlug` null = visitapp-web injoignable ; `SubscriptionPlanId` null = quotas à 0, donc `AiTokensPerMonth = 0`, donc **rien ne s'indexe** et l'IA tourne sans compteur. Réutiliser `ApplyPlanQuotas` |
|
||||||
| a | `BuildSection` ne couvre que 11 types : `SectionEvent` et `SectionParcours` tombent dans le `default` | Section non migrée, silencieusement |
|
| ~~a~~ | ⛔ **Fausse alerte — vérifiée dans l'export le 2026-08-11.** `BuildSection` couvre **exactement les types que Mongo contient**. L'enum va de `Map`=0 à `Weather`=10, puis `Event`=11 et `Parcours`=12 ; or `TabletDb.Sections.json` (327 sections) ne contient **que les valeurs 0 à 10**. `SectionEvent` et `SectionParcours` **n'existaient pas dans Mongo** — ce sont des types nés avec Postgres v3. Le `default` est un filet, pas un trou | Le kanban parlait de « perte de données » et du « scénario carnaval » : ce scénario est du **contenu à créer** dans Postgres, pas du contenu à migrer. Vérifié aussi : le renommage `SectionPuzzle` → `SectionGame` est **déjà traité** — la branche `Game` parse `OldPuzzleDTO` et pose `GameType = GameTypes.Puzzle`, et la valeur 8 n'a pas bougé |
|
||||||
| b | Collections filles jamais remplies (`QuizQuestions = new()`, `EventAgendas = new()`, aucun `GuidedPath`/`GuidedStep`) | Un quiz arrive sans ses questions |
|
| b | Collections filles jamais remplies (`QuizQuestions = new()`, `EventAgendas = new()`, aucun `GuidedPath`/`GuidedStep`) | Un quiz arrive sans ses questions |
|
||||||
| d | `Role = UserRole.ContentEditor` en dur | Plus aucun administrateur après la bascule |
|
| d | `Role = UserRole.ContentEditor` en dur | Plus aucun administrateur après la bascule |
|
||||||
| e | Colonnes `Resource` non renseignées, `SizeBytes` déduit d'un `HEAD` avalé | **L5** — appeler le calculateur C1 |
|
| e | Colonnes `Resource` non renseignées, `SizeBytes` déduit d'un `HEAD` avalé | **L5** — appeler le calculateur C1 |
|
||||||
@ -240,6 +240,41 @@ Les CGU §8 ont été réécrites le 2026-08-11 (`cgu-myinfomate.md`) et le text
|
|||||||
| I4 | `dotnet ef database update` sur la base vide, puis vérifier `postgis` **et** `vector` présents | Une base en retard d'une migration fait planter l'API dès le login — c'est arrivé en local le 09/08 |
|
| I4 | `dotnet ef database update` sur la base vide, puis vérifier `postgis` **et** `vector` présents | Une base en retard d'une migration fait planter l'API dès le login — c'est arrivé en local le 09/08 |
|
||||||
| I5 | **Plan de retour arrière écrit**, avant le jour J | « Un rollback qu'on improvise à 23 h n'est pas un rollback » |
|
| I5 | **Plan de retour arrière écrit**, avant le jour J | « Un rollback qu'on improvise à 23 h n'est pas un rollback » |
|
||||||
| I6 | `pg_dump` avant, puis **rejouer instance par instance** (`instanceId=…`), en commençant par la plus petite | |
|
| I6 | `pg_dump` avant, puis **rejouer instance par instance** (`instanceId=…`), en commençant par la plus petite | |
|
||||||
|
|
||||||
|
**Plans — décisions du 2026-08-11, à ne pas re-trancher.**
|
||||||
|
|
||||||
|
**1. Les lignes en base sont alignées sur la grille de tarifs** (migration `AlignSubscriptionPlansWithPricing`, appliquée). La base semait `Starter` / `Standard` / `Premium` / `Essentiel` : noms **et quotas** désalignés. Corrigé :
|
||||||
|
|
||||||
|
| Id | Nom | Stockage | Jetons IA | Stats | Rétention | Avancées |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| `plan-essentiel` | Essentiel | 1 GB | **0** (non inclus) | ✓ | 30 j | ✗ |
|
||||||
|
| `plan-pro` | Pro | 15 GB | **0** (non inclus) | ✓ | 30 j | ✗ |
|
||||||
|
| `plan-premium` | Premium | 50 GB | 20 M (~2 000 req) | ✓ | 395 j | ✓ |
|
||||||
|
| `plan-enterprise` | Enterprise | 0 = illimité | `long.MaxValue` | ✓ | 395 j | ✓ |
|
||||||
|
|
||||||
|
`plan-starter` **supprimé** (aucun équivalent commercial, et piège à 0 jeton). `plan-standard` → `plan-pro`, avec repointage SQL des `Instances` **avant** la suppression : EF avait scaffoldé les `DeleteData` en tête, ce qui aurait buté sur la clé étrangère ou laissé des instances sans plan, donc à quotas nuls.
|
||||||
|
|
||||||
|
⚠️ **Sémantique du `0`, asymétrique et volontaire** : pour le stockage `0` = illimité, pour les jetons `0` = pas d'IA. D'où la sentinelle `long.MaxValue` sur Enterprise — un `0` l'aurait privé d'assistant. Ne pas « harmoniser » sans repasser dans `CheckQuota`, `AiController` et `SectionIndexingInterceptor`.
|
||||||
|
|
||||||
|
⚠️ **Le plan ne porte que 5 champs.** « App native », « offline + beacons », « push », « traduction automatique » sont dans la grille commerciale mais **pas dans la table** : ils se règlent par instance. La base ne les applique pas, l'affectation le fait.
|
||||||
|
|
||||||
|
**2. Add-on IA sur Essentiel.** L'IA n'est pas incluse dans Essentiel ni Pro, mais se vend en add-on activé à la main après paiement. **Aucun code à écrire** : `ApplyPlanQuotas` ne recopie les quotas du plan que si le plan change, donc surcharger `Instance.AiTokensPerMonth` survit — le commentaire de la méthode le prévoit (« un client peut recevoir un geste commercial sans changer de plan »).
|
||||||
|
|
||||||
|
> ⚠️ **Piège à connaître** : le rattrapage d'indexation (`BackfillInstanceAsync`) est déclenché par `UpdateInstance`, en C#. **Activer l'add-on directement en SQL ne le déclenche pas** — le client paierait un guide qui ne connaît rien de son contenu déjà saisi. Après l'UPDATE, cliquer le bouton de relance SuperAdmin de l'écran Guide IA.
|
||||||
|
|
||||||
|
**3. Affectation des 4 clients existants** — pour la bascule, aucun client Essentiel :
|
||||||
|
|
||||||
|
| Instance Mongo | Plan | Conséquence |
|
||||||
|
|---|---|---|
|
||||||
|
| MyInfoMate instance | `plan-premium` | IA active |
|
||||||
|
| VisitNamur instance | `plan-premium` | IA active |
|
||||||
|
| MDLF instance | `plan-pro` | ⚠️ **pas d'IA** |
|
||||||
|
| Fort Saint-Héribert instance | `plan-pro` | ⚠️ **pas d'IA** |
|
||||||
|
|
||||||
|
> ⚠️ **À arbitrer avant le lot H** : Pro n'inclut pas l'IA, donc rien ne s'indexera pour MDLF et le Fort et leur guide ne répondra jamais. Sur 4 instances, la chaîne RAG ne serait éprouvée que sur 2 — or le lien **L14** demande justement de tester le post-filtrage HNSW **à deux instances au moins**. Deux sorties : les passer en Premium le temps des tests, ou leur poser un quota IA à la main (l'add-on ci-dessus), en pensant au rattrapage d'indexation.
|
||||||
|
|
||||||
|
**4. Écart restant, hors bascule** : la FAQ de `myinfomate-landing` (`src/data/segments.ts`) appelle encore le plan à 179€ « **Bundle** » — **41 occurrences en 4 langues** — alors que les cartes de tarifs disent « Premium ». Un prospect qui lit la grille puis la FAQ voit deux noms pour la même offre. Chantier de texte commercial, sans effet sur la migration.
|
||||||
|
|
||||||
| I7 | Vérifications post-bascule : login manager-app, une app visiteur **avec sa clé API**, un parcours, une carte, un PDF, un quiz avec ses questions | Les écarts b et c ne se voient qu'ici |
|
| I7 | Vérifications post-bascule : login manager-app, une app visiteur **avec sa clé API**, un parcours, une carte, un PDF, un quiz avec ses questions | Les écarts b et c ne se voient qu'ici |
|
||||||
| I8 | Bascule DNS / API, Mongo gardé en lecture seule quelques jours, `pg_dump` après | |
|
| I8 | Bascule DNS / API, Mongo gardé en lecture seule quelques jours, `pg_dump` après | |
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user