Compare commits
2 Commits
2944fb5a05
...
29da4fcb83
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29da4fcb83 | ||
|
|
5eff5b1687 |
12
STATUS.md
12
STATUS.md
@ -180,7 +180,17 @@ Dix-neuf chantiers de canaux et d'IA, chacun avec son plan détaillé. État au
|
||||
- ✅ **`/assistant-ia` livrée le 2026-09-10 dans les 4 langues** (relue par Thomas en FR) — 6 FAQ par langue, `hreflang` complet. **62 pages prérendues, 54 URLs au sitemap.** Au passage, les liens légaux des footers sont passés en `<Link>` : le lint est à **0 erreur** (15 avant).
|
||||
- ✅ **CGU publiées le 2026-09-10** sur `myinfomate.be/conditions-generales` — le lien de la case de consentement de `/signup` pointait jusque-là vers `/{lang}#`, c'est-à-dire nulle part. Lien ajouté aussi dans les pieds de page des 4 langues et dans le sitemap. **Deux contradictions corrigées dans [cgu-myinfomate.md](cgu-myinfomate.md)** : §6.1 citait Starter/Standard (2 et 10 Go) et §7.1 réservait l'IA aux « plans Standard et Premium ». Ce fichier reste la source ; la page Next en est le rendu, à tenir synchrone.
|
||||
- ⚠️ **Reste dû : la validation juridique des CGU** (jamais faite, le document le dit depuis avril) et le **DPA** qu'un acheteur public demandera. Carte kanban dédiée ; à faire **avant** d'ouvrir l'inscription à de vrais clients payants, pas avant la mise en prod technique.
|
||||
- ⏭️ **Prochain** : vocabulaire acheteur dans les 6 segments, puis page marchés publics. **Angle validé le 10/09** : MyInfoMate a été retenu sur **cahier des charges publié** par Visit Namur — c'est la preuve à mettre en avant. ⚠️ Aucun document d'appel d'offres n'existe encore (attestations fiscale/ONSS, DPA RGPD, attestations de bonne exécution) : la page ne doit rien promettre à ce sujet.
|
||||
- ✅ **Vocabulaire acheteur injecté dans les 6 segments, en français, le 2026-09-10** — le site n'écrivait « RGPD », « marché public », « accessibilité » ni « médiation numérique` nulle part. Ajouté par segment : une FAQ **RGPD** (les 6), une FAQ **marchés publics** (5 — pas les hôtels, secteur privé), une FAQ **accessibilité** disant franchement qu'il n'y a **ni certification Access-i ni audit** (3 segments publics). L'argument central : Visit Namur, retenu sur **cahier des charges publié**.
|
||||
- ✅ **Trois chantiers techniques bouclés le 2026-09-10** : **FAQ de la page d'accueil** (8 questions ×4 langues + `FAQPage` — la page qu'un LLM atteint en premier n'en avait aucune), **`BreadcrumbList`** sur segments, cas clients, tarifs et assistant IA, et **vraies dates dans le sitemap** (toutes les URLs portaient la date du build ; constante `LAST_MODIFIED` en tête de `sitemap.ts`, à mettre à jour avec le contenu).
|
||||
- ✅ **FAQ des segments traduites le 2026-09-10** : 42 items en EN/NL/DE, parité atteinte dans les 4 langues. Et **images recompressées** — 1,1 Mo économisé sur trois fichiers (`sharp` en installation temporaire, **pas** ajouté aux dépendances ; l'ajouter en dépendance améliorerait l'optimisation d'images en prod, mais c'est une décision de déploiement, à trancher avec le Dockerfile).
|
||||
- ✅ **Captures d'écran de la landing renouvelées le 2026-09-10** — Thomas a fourni les vraies captures de la V3 (app du Fort) : accueil sombre en grille bento et fiche article dans le hero, liste des sections dans le mockup « white label ». Les textes alternatifs, jusque-là en anglais et décrivant l'ancienne interface, sont réécrits et **localisés dans les 4 langues** (`imgAlt` dans `translations.ts`).
|
||||
- ⚠️ `public/google-maps-route.png` (699 Ko) n'est **référencé nulle part** dans `src/` — supprimable, pas supprimé. ⚠️ Le hero utilise encore `map_generated.png`, une carte **générée**, pas une capture réelle.
|
||||
- ✅ **Trois pages de plus le 2026-09-10, en 4 langues** : `/marches-publics` (argument : Visit Namur attribué sur cahier des charges publié), `/borne-kiosk` et `/visite-hors-ligne`. Gabarit partagé `components/ContentPage.tsx`. Le pied de page a désormais une colonne « Solutions » qui lie les 5 pages produit. **75 pages prérendues, 67 URLs au sitemap.**
|
||||
- ✅ **`sharp` ajouté aux dépendances, sur mesure et non sur croyance** : sans lui `/_next/image` renvoyait le JPEG source (64 Ko), avec lui du WebP (26 Ko). ⚠️ **À confirmer au premier build Docker** : le lockfile a été généré sous Windows et sharp installe des binaires par plateforme ; si `npm ci` sur Alpine ne prend pas la variante `linuxmusl`, il faudra une ligne dans le Dockerfile. Le Dockerfile n'a **pas** été modifié.
|
||||
- ✅ **Pages légales, blog et comparatifs livrés le 2026-09-10.** Légales : mentions et confidentialité traduites en 4 langues, CGU laissées en français avec avis traduit (un juriste va les corriger, traduire maintenant serait à refaire) ; les 3 pages passent sous `/{lang}/…` et les anciennes URLs redirigent vers la langue du visiteur. Blog `/fr/ressources` avec 2 articles. **Comparatifs** `myinfomate-vs-smartify` et `-vs-stqry`, **prix relevés à la source le 10/09 et datés sur la page**. **89 pages prérendues, 81 URLs au sitemap.**
|
||||
- ⏸️ **Témoignages clients écartés par Thomas** : il ne veut pas solliciter les clients pour l'instant. À rouvrir si un client en propose un.
|
||||
- ⏭️ **Reste au plan SEO** : deux pages XR à écrire quand les modules seront démontrables — **`/lunettes-connectees` et `/casque-vr`**, cette dernière ajoutée le 10/09 à la demande de Thomas.
|
||||
- ⚠️ **Les prix des concurrents vieillissent** : la page comparative affiche sa date de relevé. À revérifier avant toute campagne qui s'appuie dessus. ⚠️ Toujours aucun document d'appel d'offres (attestations fiscale/ONSS, DPA, attestations de bonne exécution) : ne rien promettre à ce sujet.
|
||||
- ⚠️ **Posts LinkedIn en deux vagues** : les posts sur des déploiements réels peuvent partir maintenant ; ceux qui poussent à l'inscription (IA, prix, essai) attendent la bascule prod et un onboarding testé.
|
||||
|
||||
---
|
||||
|
||||
21
kanban.html
21
kanban.html
@ -462,7 +462,7 @@
|
||||
<div class="stat"><span class="n n-info">1</span><span class="k">Migration v3</span></div>
|
||||
<div class="stat"><span class="n n-warn">2</span><span class="k">Bugs ouverts</span></div>
|
||||
<div class="stat"><span class="n">12</span><span class="k">À tester</span></div>
|
||||
<div class="stat"><span class="n">38</span><span class="k">Planifié</span></div>
|
||||
<div class="stat"><span class="n">39</span><span class="k">Planifié</span></div>
|
||||
<div class="stat"><span class="n n-gate">9</span><span class="k">Bascule prod</span></div>
|
||||
<div class="stat"><span class="n n-good">63</span><span class="k">Fait récemment</span></div>
|
||||
</section>
|
||||
@ -686,7 +686,7 @@
|
||||
|
||||
<!-- PLANIFIÉ -->
|
||||
<section class="col" style="--stripe: var(--ink-3)">
|
||||
<div class="col-head"><h2>Planifié</h2><span class="count">38</span></div>
|
||||
<div class="col-head"><h2>Planifié</h2><span class="count">39</span></div>
|
||||
<div class="stack">
|
||||
|
||||
<article class="card" data-area="visitapp" data-horizon="v1">
|
||||
@ -877,11 +877,15 @@
|
||||
</article>
|
||||
|
||||
<article class="card" data-area="commercial" data-horizon="v1">
|
||||
<div class="card-meta"><span class="tag">myinfomate-landing</span><span class="tag">seo</span><span class="tag">linkedin</span><span class="flag f-good">Démarré 10/09 · actions 1-9 faites</span></div>
|
||||
<div class="card-meta"><span class="tag">myinfomate-landing</span><span class="tag">seo</span><span class="tag">linkedin</span><span class="flag f-good">Démarré 10/09 · 18 des 21 actions faites</span></div>
|
||||
<h3>Plan SEO/GEO de la landing et lancement LinkedIn</h3>
|
||||
<p><strong>Audit du 09/09 : 21 actions classées par rapport impact/effort.</strong> Faites le 10/09 et vérifiées dans le HTML servi : titres <code>h2</code>/<code>h3</code>, schema <code>Organization</code> ancré en Belgique avec la TVA, trois offres dans le schema, les 9 modules de la home enfin dans le HTML, liens morts, <code>llms.txt</code> en français, <strong>prérendu statique rétabli</strong> (58 pages, le layout racine est passé dans <code>[lang]</code>) et une page <strong><code>/tarifs</code></strong> avec FAQ tarifaire. <strong>Stagé, pas committé.</strong></p>
|
||||
<p><strong><code>/assistant-ia</code> est écrite le 10/09, en français seulement</strong> (~850 mots, 6 FAQ, schema <code>FAQPage</code>) : en attente de relecture, puis traduction NL/EN/DE. Les autres langues répondent 404, c'est volontaire.</p>
|
||||
<p><strong>Suite</strong> : vocabulaire acheteur dans les 6 segments, puis page marchés publics — <strong>preuve à mettre en avant, confirmée le 10/09 : Visit Namur a été gagné sur cahier des charges publié</strong>, mais ⚠️ aucun document d'appel d'offres n'existe encore, donc ne rien promettre. Les frais de mise en place restent <strong>sans montant, par décision de Thomas</strong> (carte 180).</p>
|
||||
<p><strong>Vocabulaire acheteur injecté dans les 6 segments FR le 10/09</strong> : une FAQ RGPD partout, une FAQ marchés publics dans les 5 segments publics, une FAQ accessibilité qui assume l'absence de certification Access-i. ⚠️ <strong>Pas encore traduit</strong> en NL/EN/DE.</p>
|
||||
<p>Ajouté ensuite le même jour : <strong>FAQ de la page d'accueil</strong> (8 questions ×4 langues + <code>FAQPage</code>), <strong><code>BreadcrumbList</code></strong> sur toutes les pages profondes, et de <strong>vraies dates dans le sitemap</strong> à la place de la date de build.</p>
|
||||
<p>Puis <strong>42 items de FAQ traduits</strong> en EN/NL/DE (parité dans les 4 langues) et <strong>images recompressées</strong> : 1,1 Mo économisé, <code>sharp</code> en installation temporaire seulement. ⚠️ <code>public/google-maps-route.png</code> (699 Ko) n'est référencé nulle part. Puis <strong>captures d'écran renouvelées avec les vraies vues de la V3</strong> (accueil bento sombre, fiche article, liste des sections) et <strong>textes alternatifs localisés</strong> dans les 4 langues.</p>
|
||||
<p>Le 10/09 également : <strong>trois pages en 4 langues</strong> — <code>/marches-publics</code>, <code>/borne-kiosk</code>, <code>/visite-hors-ligne</code> — un gabarit partagé <code>ContentPage.tsx</code>, une colonne « Solutions » dans le pied de page, et <strong><code>sharp</code> en dépendance</strong> (mesuré : 64 Ko de JPEG servis sans lui, 26 Ko de WebP avec — ⚠️ à confirmer au premier build Docker).</p>
|
||||
<p><strong>Suite</strong> : pages comparatives — <strong>preuve à mettre en avant, confirmée le 10/09 : Visit Namur a été gagné sur cahier des charges publié</strong>, mais ⚠️ aucun document d'appel d'offres n'existe encore, donc ne rien promettre. Les frais de mise en place restent <strong>sans montant, par décision de Thomas</strong> (carte 180).</p>
|
||||
<p><strong>LinkedIn</strong> : vitrine MyInfoMate créée sous Unov, fiche produit soumise. Huit posts rédigés en deux vagues : ⚠️ ceux qui poussent à l'inscription attendent la bascule prod.</p>
|
||||
<span class="src">myinfomate-landing/audit-seo-geo.md §0 · DOCS/linkedin-posts-lancement.md</span>
|
||||
</article>
|
||||
@ -1084,6 +1088,15 @@
|
||||
<span class="src">v2/vr-quest-unity-plan.md §2 (lots V-4, V-5), §4, §5 · roadmap.md — section XR</span>
|
||||
</article>
|
||||
|
||||
<article class="card" data-area="commercial" data-horizon="v2">
|
||||
<div class="card-meta"><span class="tag">myinfomate-landing</span><span class="tag">seo</span><span class="tag">xr</span><span class="flag f-warn">À écrire seulement quand chaque module est démontrable</span></div>
|
||||
<h3>Pages XR de la landing — lunettes connectées et casque VR</h3>
|
||||
<p><strong>Deux pages, pas une</strong> (arbitré le 10/09) : <code>/lunettes-connectees</code> pour l'add-on Ray-Ban Meta et <code>/casque-vr</code> pour le canal immersif Meta Quest. Les deux publics et les deux modèles économiques diffèrent — un add-on mensuel d'un côté, un palier Immersif de l'autre — et les mettre sur une seule page brouillerait les deux.</p>
|
||||
<p><strong>Aujourd'hui, la landing n'en dit qu'une ligne</strong> : « Meta Quest et lunettes connectées » dans le 4<sup>e</sup> mode de déploiement, avec un badge « Bientôt ». C'est honnête et c'est suffisant tant qu'il n'y a rien à montrer.</p>
|
||||
<p>⏱️ <strong>Condition d'écriture : un module démontrable.</strong> Publier une page produit sur une fonctionnalité qu'on ne peut pas faire tourner en rendez-vous se retourne contre nous — c'est le même raisonnement que pour la vague 2 des posts LinkedIn. Le reste du contenu (positionnement, prix, arguments) est déjà écrit dans les deux docs de la colonne source.</p>
|
||||
<span class="src">myinfomate-landing/audit-seo-geo.md action 19 · DOCS/v2/vr-quest-unity-plan.md · DOCS/rayban-meta-integration.md</span>
|
||||
</article>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@ -3,10 +3,14 @@ title: Plan SEO/GEO de la landing et lancement LinkedIn
|
||||
area: commercial
|
||||
horizon: v1
|
||||
tags: myinfomate-landing, seo, linkedin
|
||||
flag: good | Démarré 10/09 · actions 1-9 faites
|
||||
flag: good | Démarré 10/09 · 18 des 21 actions faites
|
||||
src: myinfomate-landing/audit-seo-geo.md §0 · DOCS/linkedin-posts-lancement.md
|
||||
---
|
||||
<p><strong>Audit du 09/09 : 21 actions classées par rapport impact/effort.</strong> Faites le 10/09 et vérifiées dans le HTML servi : titres <code>h2</code>/<code>h3</code>, schema <code>Organization</code> ancré en Belgique avec la TVA, trois offres dans le schema, les 9 modules de la home enfin dans le HTML, liens morts, <code>llms.txt</code> en français, <strong>prérendu statique rétabli</strong> (58 pages, le layout racine est passé dans <code>[lang]</code>) et une page <strong><code>/tarifs</code></strong> avec FAQ tarifaire. <strong>Stagé, pas committé.</strong></p>
|
||||
<p><strong><code>/assistant-ia</code> est écrite le 10/09, en français seulement</strong> (~850 mots, 6 FAQ, schema <code>FAQPage</code>) : en attente de relecture, puis traduction NL/EN/DE. Les autres langues répondent 404, c'est volontaire.</p>
|
||||
<p><strong>Suite</strong> : vocabulaire acheteur dans les 6 segments, puis page marchés publics — <strong>preuve à mettre en avant, confirmée le 10/09 : Visit Namur a été gagné sur cahier des charges publié</strong>, mais ⚠️ aucun document d'appel d'offres n'existe encore, donc ne rien promettre. Les frais de mise en place restent <strong>sans montant, par décision de Thomas</strong> (carte 180).</p>
|
||||
<p><strong>Vocabulaire acheteur injecté dans les 6 segments FR le 10/09</strong> : une FAQ RGPD partout, une FAQ marchés publics dans les 5 segments publics, une FAQ accessibilité qui assume l'absence de certification Access-i. ⚠️ <strong>Pas encore traduit</strong> en NL/EN/DE.</p>
|
||||
<p>Ajouté ensuite le même jour : <strong>FAQ de la page d'accueil</strong> (8 questions ×4 langues + <code>FAQPage</code>), <strong><code>BreadcrumbList</code></strong> sur toutes les pages profondes, et de <strong>vraies dates dans le sitemap</strong> à la place de la date de build.</p>
|
||||
<p>Puis <strong>42 items de FAQ traduits</strong> en EN/NL/DE (parité dans les 4 langues) et <strong>images recompressées</strong> : 1,1 Mo économisé, <code>sharp</code> en installation temporaire seulement. ⚠️ <code>public/google-maps-route.png</code> (699 Ko) n'est référencé nulle part. Puis <strong>captures d'écran renouvelées avec les vraies vues de la V3</strong> (accueil bento sombre, fiche article, liste des sections) et <strong>textes alternatifs localisés</strong> dans les 4 langues.</p>
|
||||
<p>Le 10/09 également : <strong>trois pages en 4 langues</strong> — <code>/marches-publics</code>, <code>/borne-kiosk</code>, <code>/visite-hors-ligne</code> — un gabarit partagé <code>ContentPage.tsx</code>, une colonne « Solutions » dans le pied de page, et <strong><code>sharp</code> en dépendance</strong> (mesuré : 64 Ko de JPEG servis sans lui, 26 Ko de WebP avec — ⚠️ à confirmer au premier build Docker).</p>
|
||||
<p><strong>Suite</strong> : pages comparatives — <strong>preuve à mettre en avant, confirmée le 10/09 : Visit Namur a été gagné sur cahier des charges publié</strong>, mais ⚠️ aucun document d'appel d'offres n'existe encore, donc ne rien promettre. Les frais de mise en place restent <strong>sans montant, par décision de Thomas</strong> (carte 180).</p>
|
||||
<p><strong>LinkedIn</strong> : vitrine MyInfoMate créée sous Unov, fiche produit soumise. Huit posts rédigés en deux vagues : ⚠️ ceux qui poussent à l'inscription attendent la bascule prod.</p>
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
---
|
||||
title: Pages XR de la landing — lunettes connectées et casque VR
|
||||
area: commercial
|
||||
horizon: v2
|
||||
tags: myinfomate-landing, seo, xr
|
||||
flag: warn | À écrire seulement quand chaque module est démontrable
|
||||
src: myinfomate-landing/audit-seo-geo.md action 19 · DOCS/v2/vr-quest-unity-plan.md · DOCS/rayban-meta-integration.md
|
||||
---
|
||||
<p><strong>Deux pages, pas une</strong> (arbitré le 10/09) : <code>/lunettes-connectees</code> pour l'add-on Ray-Ban Meta et <code>/casque-vr</code> pour le canal immersif Meta Quest. Les deux publics et les deux modèles économiques diffèrent — un add-on mensuel d'un côté, un palier Immersif de l'autre — et les mettre sur une seule page brouillerait les deux.</p>
|
||||
<p><strong>Aujourd'hui, la landing n'en dit qu'une ligne</strong> : « Meta Quest et lunettes connectées » dans le 4<sup>e</sup> mode de déploiement, avec un badge « Bientôt ». C'est honnête et c'est suffisant tant qu'il n'y a rien à montrer.</p>
|
||||
<p>⏱️ <strong>Condition d'écriture : un module démontrable.</strong> Publier une page produit sur une fonctionnalité qu'on ne peut pas faire tourner en rendez-vous se retourne contre nous — c'est le même raisonnement que pour la vague 2 des posts LinkedIn. Le reste du contenu (positionnement, prix, arguments) est déjà écrit dans les deux docs de la colonne source.</p>
|
||||
467
v2/immersif-frontiere-plan.md
Normal file
467
v2/immersif-frontiere-plan.md
Normal file
@ -0,0 +1,467 @@
|
||||
# Contenu immersif — frontière entre le Studio IA et le canal XR — 📦 V2
|
||||
|
||||
> **Statut** : document de frontière, écrit le 2026-09-11. Rien de codé.
|
||||
>
|
||||
> **Ce document ne remplace ni [studio-plan.md](studio-plan.md) ni [vr-quest-unity-plan.md](vr-quest-unity-plan.md).**
|
||||
> Il tranche ce que ces deux plans se renvoient mutuellement en dépendance : le Studio met la 3D en
|
||||
> lot 11 en disant « dépend du chantier VR », et le plan VR décrit les POI sur GLB (§9) en supposant
|
||||
> un GLB qui arrive de quelque part, sans jamais dire d'où. Ce n'est pas un trou de conception, c'est
|
||||
> une frontière que personne ne tient.
|
||||
>
|
||||
> ⚠️ **Rien ici n'est V1.** La bascule Postgres et le backlog V1 passent avant. Et le gate du Studio
|
||||
> reste celui du lot 4 : si un conservateur ne produit pas 10 images cohérentes seul, aucune ligne de
|
||||
> 3D ne s'écrit.
|
||||
|
||||
---
|
||||
|
||||
## 1. Les trois couches
|
||||
|
||||
La confusion vient de ce que « module 3D » désigne trois choses distinctes, décrites dans deux
|
||||
documents différents. Les voici séparées.
|
||||
|
||||
### Couche 1 — Ressources immersives
|
||||
|
||||
Trois nouveaux types de ressource, qui s'affichent **partout où une ressource s'affiche** :
|
||||
|
||||
```
|
||||
ResourceType += Panorama360 -- image équirectangulaire
|
||||
Video360 -- vidéo équirectangulaire
|
||||
Model3D -- GLB
|
||||
```
|
||||
|
||||
Indépendant de la VR. Indépendant de l'IA. Un client web sans casque et sans Studio en profite.
|
||||
|
||||
⚠️ **Les trois valeurs se décident d'un coup, en une migration, en fin d'enum.** Aujourd'hui
|
||||
`ResourceType` s'arrête à `Text = 10` (`Data/Resource.cs:94-110`, avec le commentaire qui interdit
|
||||
d'insérer au milieu). `studio-plan.md` §5 réserve déjà `Model3D = 11`.
|
||||
|
||||
**Décision — `Video360` est un type distinct, pas un flag `IsEquirectangular` sur `Video`.** L'enum
|
||||
distingue déjà `Image` / `ImageUrl` : un type séparé est cohérent avec l'existant et rend le filtrage
|
||||
trivial dans le sélecteur de ressource, qui est le point de passage unique de toute l'app
|
||||
(`select_resource_modal.dart:24` embarque `ResourcesScreen`).
|
||||
|
||||
### Couche 2 — Consommation
|
||||
|
||||
Trois usages de ces ressources :
|
||||
|
||||
| Usage | Porté par | Canaux |
|
||||
|---|---|---|
|
||||
| `SectionModel3D` + POI (titre, description, audio, multilingue) | une section | web, mobile, VR |
|
||||
| `ImmersiveBackground` — fond d'une visite | `Configuration` | VR, dégradé ailleurs (§4) |
|
||||
| `ImmersiveBackground` — fond du menu général | `ApplicationInstance` VR | VR |
|
||||
| Rendu immersif complet | app Quest (Unity) | VR |
|
||||
|
||||
Le back-office XR (`Device.AppType` + onglet flotte, 8-12 j) se tient debout tout seul dans cette
|
||||
couche : il rend le canal administrable et démontrable avant tout engagement sur Unity.
|
||||
|
||||
### Couche 3 — Studio IA
|
||||
|
||||
**Une source d'approvisionnement pour la couche 1, pas un module parallèle.** C'est la reformulation
|
||||
qui règle la frontière : le Studio ne possède pas ses assets, il **alimente la médiathèque**, qui
|
||||
reste la bibliothèque unique (`studio-plan.md` §3.0).
|
||||
|
||||
Ce que le Studio apporte que le client ne peut pas obtenir ailleurs, dans l'ordre de valeur :
|
||||
|
||||
1. **L'asset atterrit dans la médiathèque, référencé par une section, donc il part offline.**
|
||||
C'est le point non réplicable. Un asset généré ailleurs est un fichier à re-uploader à la main,
|
||||
et il ne part offline que s'il finit référencé par un champ de section
|
||||
(`GetReferencedResourceIds`).
|
||||
2. **L'identité visuelle est injectée côté serveur, jamais retapée.** La cohérence des quarante
|
||||
images d'un parcours, pas l'accès au modèle.
|
||||
3. **Le bon format, la bonne dimension, le bon prompt contextuel** — le titre et la description de
|
||||
la fiche alimentent le prompt, la validation affecte directement au champ cible.
|
||||
|
||||
---
|
||||
|
||||
## 2. Ce que chaque couche vend
|
||||
|
||||
**Il n'y a pas d'add-on casque.** Arbitré le 2026-08-31 (`vr-quest-unity-plan.md` §6), reconfirmé
|
||||
ici parce que la question revient : un add-on « VR » ne se vendrait que le jour où l'app Unity existe
|
||||
*et* où le client achète un casque. L'add-on **« Contenu immersif », 70 €/mois et plus**, vend la
|
||||
couche 1 — qui s'affiche déjà en web, mobile et kiosk. Un client le souscrit et en a pour son argent
|
||||
**sans casque**. Le casque est le haut de gamme de l'add-on, pas sa condition d'existence.
|
||||
|
||||
| Ce qui est vendu | Véhicule | Montant |
|
||||
|---|---|---|
|
||||
| Ressources immersives (360, GLB, POI) + l'app Quest quand elle sortira | add-on « Contenu immersif » | à partir de 70 €/mois, s'accroche à n'importe quel palier |
|
||||
| Génération IA (images, puis props et scènes) | add-on Studio, crédits dédiés | voir `studio-plan.md` §3.5 |
|
||||
| Casques | achat client | hardware |
|
||||
| Provisioning, config borne, formation, journée sur site | onboarding one-shot | 1200-1500 €, **seulement s'il y a des casques** |
|
||||
| Modélisation 3D d'atelier, photogrammétrie d'objets de collection | sur devis, hors Studio | 3 à 15 k€ |
|
||||
|
||||
### 2bis. Quota IA et crédits Studio — deux monnaies, et pourquoi
|
||||
|
||||
> **Arrêté le 2026-09-11.** La question « le Studio consomme-t-il le quota IA ? » revient à chaque
|
||||
> conversation. Réponse : **non**, et voici le critère pour ne plus se la reposer.
|
||||
|
||||
**Le critère n'est pas « IA / pas IA ». C'est « consommé en temps réel par le visiteur » contre
|
||||
« produit une fois par le client ».** Cette ligne décide du modèle de facturation parce qu'elle décide
|
||||
de la forme de la courbe d'usage.
|
||||
|
||||
| | **Quota IA** | **Crédits Studio** |
|
||||
|---|---|---|
|
||||
| Unité | tokens / mois | crédits |
|
||||
| Renouvellement | reset mensuel, non reporté | **rechargeables, expiration 12 mois** |
|
||||
| Véhicule | attribut du palier | add-on |
|
||||
| Courbe d'usage | récurrente, suit la fréquentation | **en pics** (préparation d'une expo) |
|
||||
| Couvre | chat visiteur, canal vocal, traduction | images, 3D, scènes, vidéo, **TTS pré-généré** |
|
||||
|
||||
Le reset mensuel est **juste** pour le quota IA : l'usage suit la fréquentation, il est corrélé aux
|
||||
vacances scolaires, et il est normal qu'il ne se reporte pas.
|
||||
|
||||
Il est **faux** pour le Studio. Un musée génère 200 images en trois semaines pour préparer une expo,
|
||||
puis rien pendant cinq mois. Un forfait mensuel se gaspille dix mois sur douze : le client a le
|
||||
sentiment de payer pour rien, et la capacité provisionnée ne sert pas.
|
||||
|
||||
➡️ **Correction à porter dans `studio-plan.md` §3.5** : `ImageCreditsMonthKey` et le
|
||||
`Kind: MonthlyReset` deviennent inutiles. Le `CreditLedger` est déjà append-only avec un
|
||||
`Kind: Grant` — il encaisse le modèle rechargeable **sans changement de schéma**. Gratuit à décider
|
||||
maintenant, migration en prod plus tard.
|
||||
|
||||
**Le TTS pré-généré va côté Studio**, et c'est contre-intuitif puisque c'est « de l'IA ». Trois
|
||||
raisons : il se facture au caractère et non au token, il produit un fichier (donc du stockage, comme
|
||||
une image générée), et il se déclenche par pics quand le conservateur rédige. Le mettre sur le quota
|
||||
tokens visiteur mélangerait deux courbes sans rapport.
|
||||
|
||||
**La traduction est le cas limite, laissé où il est.** Par le critère ci-dessus elle devrait être en
|
||||
crédits Studio — déclenchée par le client, une fois, produisant un asset durable. Mais elle est déjà
|
||||
sur le quota tokens, elle est très bon marché, et la déplacer ne rapporterait rien. Décision : **ne
|
||||
pas y toucher**, mais le savoir plutôt que de le redécouvrir.
|
||||
|
||||
**Vérifié dans le code le 2026-09-11 — ce que le quota IA couvre réellement :**
|
||||
|
||||
| Endpoint | Débite le quota | Note |
|
||||
|---|---|---|
|
||||
| `POST /api/Ai/chat` | ✅ `AiController.cs:394` | |
|
||||
| `POST /api/Ai/translate` | ✅ `AiController.cs:347` | |
|
||||
| `POST /api/Ai/reindex/{instanceId}` | ❌ | **Les embeddings RAG coûtent et passent gratuitement** |
|
||||
| `GET /api/Ai/insights/{instanceId}` | ❌ | idem |
|
||||
|
||||
⚠️ **Trou existant, indépendant du Studio** : deux endpoints facturés chez Google ne débitent rien.
|
||||
Et `AiTokensPerMonth` vaut `0` en Essentiel et Pro, `20_000_000` en Premium
|
||||
(`MyInfoMateDbContext.cs:607-637`) — donc le quota IA est aujourd'hui un **attribut du palier**, pas
|
||||
un add-on. À ne pas confondre avec les crédits Studio, qui sont un add-on.
|
||||
|
||||
⚠️ **L'add-on immersif doit porter sa propre enveloppe de stockage, explicite et finie, avec
|
||||
facturation du dépassement.** Un client Pro à 99 € a un quota dimensionné pour du Pro ; une vidéo 360
|
||||
de 5 minutes pèse des Go, un monde exporté en splats aussi. Le principe est posé dans
|
||||
`vr-quest-unity-plan.md` §6 — **il n'est toujours pas chiffré, et il doit l'être avant d'ouvrir la
|
||||
couche 1 à la vente.**
|
||||
|
||||
---
|
||||
|
||||
## 3. Génération de scène 3D — état réel du marché
|
||||
|
||||
> **Révisé le 2026-09-11.** Une première passe de cette analyse concluait « ne pas faire, l'assemblage
|
||||
> est la seule voie ». C'était fondé sur un état du marché périmé : la conclusion change, la limite
|
||||
> qui la motivait reste vraie.
|
||||
|
||||
### Ce qui existe
|
||||
|
||||
[Marble](https://www.worldlabs.ai/blog/marble-world-model) (World Labs) génère des environnements 3D
|
||||
persistants depuis du texte, une image, une vidéo ou un panorama, et **expose une World API depuis
|
||||
janvier 2026** — à partir de **~0,12 $ le monde en draft**. Exports : splats (SPZ/PLY), panorama 360,
|
||||
collider mesh basse résolution, et **mesh texturé GLB** sur le palier Pro, qui porte aussi les droits
|
||||
commerciaux.
|
||||
|
||||
➡️ **Ça entre dans la couche fournisseur sans rien y changer** : un `GenerationModel` de plus en base,
|
||||
`ProviderKey = "worldlabs"`, `Kind = Scene3D`. C'est exactement ce que `studio-plan.md` §3.6 a été
|
||||
conçu pour absorber.
|
||||
|
||||
### La limite qui ne bouge pas
|
||||
|
||||
Un monde Marble est une **scène capturée**, excellente vue depuis et autour de son point de vue,
|
||||
qui dégrade dès qu'on s'en éloigne. Chiffres rapportés côté Quest 3 standalone : plafond raisonnable
|
||||
autour de **500k splats** (2M restant du domaine du VR filaire), environnements cadrés sur une grille
|
||||
de ~10×10 m, et un cas mesuré à **12 fps sous Unity contre 19 dans le navigateur Oculus**. Une borne
|
||||
publique doit tenir 72 fps, huit heures par jour, sans personne à côté.
|
||||
|
||||
Et il n'y a pas de sémantique : pas de sol identifié, pas d'objets nommés, pas d'interactions. Le
|
||||
collider mesh fourni donne la collision, pas la compréhension de la scène.
|
||||
|
||||
### Position retenue
|
||||
|
||||
| Usage | Verdict |
|
||||
|---|---|
|
||||
| Fond immersif d'une visite ou du menu VR (le visiteur regarde autour de lui depuis un point fixe) | ✅ **oui**, c'est le cas d'usage nominal de la techno |
|
||||
| Monde de référence en **roomscale stationnaire** : le visiteur est *dans* la scène, sur ~3 m | ✅ **oui** — et c'est mieux qu'un assemblage de props Meshy |
|
||||
| Environnement navigable, le visiteur se déplace librement dedans | ❌ **non** en V2. Ni la perf en borne, ni la sémantique n'y sont |
|
||||
| Props d'ambiance générés depuis du texte, placés sur ancres | ✅ **oui**, faible risque : un prop raté se jette |
|
||||
|
||||
**Le cadre retenu est le roomscale stationnaire, pas un diorama.** Arbitré le 2026-09-11 : une zone
|
||||
d'environ 3 m où le visiteur tourne sur lui-même, se penche et tend le bras, mais ne se déplace pas.
|
||||
C'est exactement la zone où Marble est bon — son point de capture — et où le budget de perf tient.
|
||||
|
||||
Ce n'est pas un pis-aller : la contrainte supprime d'un coup la locomotion, les collisions, le motion
|
||||
sickness, la cohérence d'échelle au-delà du champ proche et l'essentiel du budget de perf. Et elle est
|
||||
*meilleure* produit qu'un diorama vu de l'extérieur, parce que le visiteur est **dans** la scène.
|
||||
Le but n'a jamais été de faire un jeu VR.
|
||||
|
||||
**Placement sur ancres prédéfinies, jamais libre.** Le template d'environnement Unity expose N
|
||||
snap points ; le client y accroche ses props. Un éditeur de placement libre en 3D dans un back-office
|
||||
web est un chantier à lui seul, pour un gain nul à ce stade.
|
||||
|
||||
### Image → GLB : mature en API, piégeux en produit
|
||||
|
||||
Meshy / Tripo / Rodin ont des API qui marchent, et le multi-vues améliore nettement le résultat. Mais
|
||||
ce qui sort est un objet isolé, silhouette lisible, topologie sale, texture baked, échelle et pivot
|
||||
arbitraires.
|
||||
|
||||
⚠️ **Pour un objet de collection, le problème n'est pas la qualité, c'est la véracité.** Un visiteur
|
||||
qui fait tourner « le casque de Léon » croit voir l'objet. Deux conséquences :
|
||||
|
||||
- Sur un `Model3D` généré, la provenance visible est **obligatoire, non désactivable** — contrairement
|
||||
aux images, où le badge suffit et la gravure est une option (`studio-plan.md` décision n°6).
|
||||
- L'offre doit séparer explicitement **« objet numérisé »** (photogrammétrie, sur devis, hors Studio)
|
||||
de **« illustration 3D »** (Studio). Les vendre sous le même mot est un risque réputationnel chez
|
||||
une institution scientifique.
|
||||
|
||||
### Le vrai sur-scope : l'éditeur, pas la génération
|
||||
|
||||
`vr-quest-unity-plan.md` §9 signale l'éditeur de placement de POI comme « le seul morceau non
|
||||
trivial ». Il le sous-estime : **Flutter web n'a pas de stack 3D éditable.** `model_viewer_plus` est
|
||||
une WebView autour de `<model-viewer>`, en lecture seule.
|
||||
|
||||
➡️ **Décision à prendre maintenant, parce qu'elle conditionne tout le chiffrage** : l'éditeur de POI
|
||||
3D est une **page three.js embarquée en iframe**, pas un widget Flutter. Précédent dans le repo : la
|
||||
démo villa d'Echternach (`visitapp-web/src/app/demo/villa-echternach/scene.ts`).
|
||||
|
||||
---
|
||||
|
||||
## 4. `ImmersiveBackground` — un type, deux porteurs
|
||||
|
||||
`Configuration` porte aujourd'hui `ImageId` et `LoaderImageId`, rien d'immersif. Poser un
|
||||
`Configuration.BackgroundResourceId` à plat, puis un autre champ sur l'`ApplicationInstance`, puis un
|
||||
troisième pour la scène, donne quatre champs « background » incohérents dans six mois.
|
||||
|
||||
```
|
||||
ImmersiveBackground
|
||||
ResourceId
|
||||
Kind -- Pano | Video360 | Scene3D
|
||||
FallbackResourceId? -- 2D, pour les canaux qui ne savent pas rendre
|
||||
```
|
||||
|
||||
Porté par **`Configuration`** (le fond d'une visite) **et** par l'**`ApplicationInstance` VR** (le
|
||||
fond du menu général — l'équivalent de home v3 côté mobile). Un seul type, deux porteurs, pas deux
|
||||
modèles.
|
||||
|
||||
**Dégradation par canal, écrite dans le contrat** — sinon les fonds casseront silencieusement :
|
||||
|
||||
| Canal | `Pano` | `Video360` | `Scene3D` |
|
||||
|---|---|---|---|
|
||||
| VR (Quest) | rendu | rendu | rendu |
|
||||
| Web | visite pivotante | visite pivotante | fallback 2D |
|
||||
| Mobile | fallback 2D | fallback 2D | fallback 2D |
|
||||
| Kiosk | fallback 2D | fallback 2D | fallback 2D |
|
||||
|
||||
Chaque canal déclare ce qu'il sait rendre ; le fallback est `Configuration.ImageId` par défaut.
|
||||
|
||||
---
|
||||
|
||||
## 5. Décisions de rétro-compatibilité, du plus cher au moins cher
|
||||
|
||||
Les points **1 à 5 doivent être écrits dans `studio-plan.md` avant sa première migration.** Les
|
||||
suivants peuvent s'écrire au fil de l'eau.
|
||||
|
||||
### 1. Pipeline d'ingestion unique côté serveur
|
||||
|
||||
**Le trou le plus cher, et il est structurel, pas accidentel.** Aujourd'hui **l'upload est fait par
|
||||
le navigateur en direct** (`resources_screen.dart:247-256`) ; le backend ne sait que supprimer
|
||||
(`IResourceBlobService.DeleteAsync`). Le Studio, lui, produit côté serveur et post-traite **à la
|
||||
validation d'un brouillon**.
|
||||
|
||||
➡️ Un GLB **uploadé** ne traverserait aucun traitement, un GLB **généré** traverserait le chemin
|
||||
Studio. Deux chemins par construction.
|
||||
|
||||
- [ ] Déplacer le point de passage de « validation d'un asset Studio » à **« ingestion de tout asset,
|
||||
quelle que soit sa provenance »**
|
||||
- [ ] Un seul service de post-traitement, appelé par les deux chemins
|
||||
- [ ] Le lot 0 (`UploadAsync`, `CopyAsync`, `ProbeSizeAsync`) est le prérequis mais **ne suffit pas**
|
||||
|
||||
Coût du retrofit : l'upload navigateur direct est partout dans manager-app, et il faudrait retraiter
|
||||
la base d'assets existante.
|
||||
|
||||
### 2. Normalisation canonique des GLB
|
||||
|
||||
- [ ] Pivot recentré, échelle normalisée, up-axis fixé — **déterministes**
|
||||
- [ ] Budgets de validation (tris, taille de texture, poids) : **rejet**, pas réparation
|
||||
- [ ] Draco + KTX2 dans le même passage
|
||||
- [ ] `Model3DVersion` sur la ressource
|
||||
|
||||
Coût du retrofit : **tout POI posé avant est perdu.** C'est ce qui rend ce point non négociable, pas
|
||||
l'élégance du pipeline.
|
||||
|
||||
### 3. Invalidation et repositionnement des POI
|
||||
|
||||
Absent des deux plans. Et c'est structurellement plus grave qu'en géo : une lat/lon survit à un
|
||||
changement de fond de carte, un (x,y,z) local est **détruit** par un changement de pivot, d'échelle ou
|
||||
d'up-axis.
|
||||
|
||||
- [ ] POI attachés à `(resourceId, modelVersion)`
|
||||
- [ ] Au remplacement ou à la régénération : POI **conservés et marqués « à revalider »**, jamais
|
||||
supprimés en silence
|
||||
- [ ] Écran de repositionnement dans l'éditeur
|
||||
|
||||
Peu de code si pris tôt. Coûteux en confiance client si découvert en prod.
|
||||
|
||||
### 4. Lignage en colonnes typées
|
||||
|
||||
`Resource.AiProvenance` (jsonb) distingue uploadé (null) de généré (non-null) et liste des
|
||||
`referenceResourceIds[]`. **Mais un tableau dans un jsonb n'est pas un lignage requêtable**, et rien
|
||||
ne couvre un GLB **dérivé** — reprocessé, décimé, regénéré depuis le même jeu de photos.
|
||||
|
||||
- [ ] `Resource.Origin` : `Uploaded | Generated | Derived` — **colonne**, pas jsonb
|
||||
- [ ] `Resource.SourceResourceId` nullable — le lignage parent/enfant
|
||||
- [ ] `AiProvenance` reste pour le détail (prompt effectif, seed, version d'identité)
|
||||
|
||||
Coût du retrofit : migration de données sur des assets déjà en base.
|
||||
|
||||
### 5. Renommer la monnaie de crédits — ✅ **porté dans `studio-plan.md` le 2026-09-11**
|
||||
|
||||
`ImageCreditsPerMonth`, `ImageCreditsThisMonth`, `ImageCreditsMonthKey`, `ImageCreditsHardCap`,
|
||||
`SubscriptionPlan.ImageCreditsPerMonth`. Or une 3D coûte 10 à 50 fois une image, et un monde Marble
|
||||
n'est pas une image du tout.
|
||||
|
||||
- [x] `ImageCredits*` → **`StudioCredits*`** partout
|
||||
- [x] `GenerationModel.CreditCost` déjà par modèle : rien d'autre à faire côté tarification
|
||||
- [x] **Et le modèle change aussi** : crédits **rechargeables à expiration 12 mois** au lieu d'un
|
||||
quota mensuel. Un musée génère en pics, pas linéairement — un forfait mensuel se gaspille dix
|
||||
mois sur douze. Voir `studio-plan.md` §3.5 et le §2bis ci-dessus
|
||||
|
||||
**Gratuit aujourd'hui. Migration de colonnes en prod plus tard.** Le retrofit le moins cher à éviter
|
||||
et le plus bête à subir. ➡️ **Fait** : décision n°3 du tableau §2, bloc §3.5, schéma §5 et lot 1 de
|
||||
`studio-plan.md` sont à jour. Reste ouvert : le mapping Stripe `checkout.session.completed` →
|
||||
`Kind: Grant` pour la recharge.
|
||||
|
||||
### 6. Contrat fournisseur : multi-fichier et par kind
|
||||
|
||||
`ProviderResult` est pensé mono-fichier image. Une génération 3D retourne GLB + preview + parfois
|
||||
textures séparées ; un monde retourne splat + collider mesh + panorama.
|
||||
|
||||
- [ ] `ProviderResult` multi-fichier
|
||||
- [ ] `GenerationKind` += `Model3D`, `SceneProp`, `Scene3D`
|
||||
- [ ] **Timeout et politique de retry par kind** — le `PollFallback` à +90 s et le polling front à 2 s
|
||||
de `studio-plan.md` §3.7 sont dimensionnés pour un job image de 20-60 s
|
||||
- [ ] **Job composite** : générer 8 props est un job parent + N enfants, pas un job
|
||||
|
||||
### 7. `ImmersiveBackground` comme type réutilisable
|
||||
|
||||
Voir §4. Deux porteurs, un type, dégradation par canal dans le contrat.
|
||||
|
||||
### 8. Les trois valeurs `ResourceType` d'un coup
|
||||
|
||||
Voir §1, couche 1.
|
||||
|
||||
### 9. Éditeur 3D = iframe three.js
|
||||
|
||||
Décision d'architecture, pas d'implémentation. Voir §3.
|
||||
|
||||
### 10. Chiffrer l'enveloppe de stockage de l'add-on immersif
|
||||
|
||||
Voir §2. Posé en principe le 31/08, jamais chiffré.
|
||||
|
||||
### 11. Provenance obligatoire sur un `Model3D` généré
|
||||
|
||||
Voir §3. Et séparer « objet numérisé » de « illustration 3D » dans l'offre.
|
||||
|
||||
---
|
||||
|
||||
## 6. Droits et modération — ce qui reste ouvert
|
||||
|
||||
Couvert par `studio-plan.md` : `rightsHolder` = l'instance (les droits sont au client, écrit dans la
|
||||
donnée), provenance complète, badge visiteur traduit dans les langues de la configuration, et la
|
||||
redirection des personnes identifiables vers les personnages.
|
||||
|
||||
**Pas couvert, et spécifique à la 3D** : rien sur les objets dont le client **n'a pas** les droits —
|
||||
prêts, dépôts, collections tierces. C'est le quotidien d'un musée, et générer un GLB depuis la photo
|
||||
d'un objet en dépôt n'est pas anodin.
|
||||
|
||||
➡️ Traitement retenu : **CGU + une mention explicite dans l'écran de génération 3D**, pas de
|
||||
vérification automatique. Pas de modération automatique entrée/sortie non plus. Acceptable au stade
|
||||
pilote — **à condition de l'assumer par écrit**, pas de le découvrir.
|
||||
|
||||
---
|
||||
|
||||
## 7. Chemin critique
|
||||
|
||||
Ce n'est pas celui qu'on croit. La génération 3D est en toute fin, et c'est la brique la **moins**
|
||||
risquée de la liste, parce qu'à ce stade tout ce qui la consomme existe et est validé.
|
||||
|
||||
```
|
||||
Lot 0 — socle de stockage serveur (prérequis dur, sert aussi le TTS)
|
||||
└─ + pipeline d'ingestion unique (décision n°1)
|
||||
└─ Ressource 360° (le plus petit des trois chantiers médias)
|
||||
└─ SectionModel3D + POI (GeoPoint réutilisé à 80 %)
|
||||
└─ Back-office XR (8-12 j, se tient debout tout seul)
|
||||
└─ Studio images (lots 1 à 6)
|
||||
└─ ⛔ GATE lot 4 : un conservateur, 10 images, seul
|
||||
└─ Studio 3D + scènes
|
||||
└─ App Unity (go/no-go client pilote)
|
||||
```
|
||||
|
||||
Le go/no-go de l'app Unity reste conditionné à **un client pilote disposant déjà de contenu immersif**
|
||||
— et la couche 1 rend cette condition atteignable, puisqu'elle permet au client de *fabriquer* ce
|
||||
contenu au lieu de devoir le posséder d'avance. C'est le changement le plus important qu'apporte le
|
||||
Studio au dossier XR.
|
||||
|
||||
---
|
||||
|
||||
## 8. Ce qu'on ne fait pas
|
||||
|
||||
- **Environnement VR navigable** en V2 — roomscale stationnaire ~3 m seulement (§3)
|
||||
- **Placement libre de props** — ancres prédéfinies
|
||||
- **Locomotion en VR** — le visiteur tourne sur lui-même, il ne marche pas
|
||||
- **Les mécaniques de jeu du §9** — notées, pas planifiées
|
||||
- **Photogrammétrie / fac-similé d'objets de collection** — sur devis, hors Studio
|
||||
- **Modération automatique** entrée/sortie — CGU + provenance + `rightsHolder` (§6)
|
||||
- **Retopologie ou upscaling automatique** — budgets de validation et rejet, pas de réparation
|
||||
- **Refonte du routing de manager-app** — les deux `switch` numérotés en dur de `main_screen.dart`
|
||||
sont acceptés tels quels, comme dans `studio-plan.md`
|
||||
|
||||
---
|
||||
|
||||
## 9. Mécaniques de jeu immersives — 📝 idées notées, rien de planifié
|
||||
|
||||
> **Noté le 2026-09-11, à la suite du canal VR — pas dans son périmètre.** Aucune de ces mécaniques
|
||||
> n'est chiffrée ni engagée. Elles sont ici pour ne pas être reperdues, et parce que **deux d'entre
|
||||
> elles réutilisent des données qui existent déjà**, ce qui change leur coût relatif.
|
||||
|
||||
**Le principe structurant, à ne pas perdre** : un jeu configurable par le client **n'est pas un
|
||||
moteur de jeu, c'est un type de section**. Trois mécaniques génériques couvrent l'essentiel de ce qui
|
||||
a du sens en musée, et toutes tiennent dans les ~3 m du roomscale stationnaire. Le client compose ;
|
||||
un vrai jeu sur mesure reste un devis.
|
||||
|
||||
| Mécanique | Ce que c'est | Données | Coût |
|
||||
|---|---|---|---|
|
||||
| **Répondre** | Quiz immersif : question devant, réponses sur 3-4 panneaux autour, réponse au regard ou à la main. Fond = `ImmersiveBackground` de la configuration | **`SectionQuiz`, déjà là** | rendu seul, **config nulle** |
|
||||
| **Trouver** | Chasse aux détails dans un pano 360 : « trouve les 5 détails », « repère les 3 erreurs ». Le client pose des hotspots | même geste que poser des POI → **le même éditeur iframe sert deux fois** | faible, et **ça marche aussi en web** sur pano pivotant → se vend sans casque |
|
||||
| **Ordonner** | Tri chronologique ou logique : attraper des objets autour de soi et les ranger. Frise, étapes d'un procédé | **`OrderedTranslationAndResource`, déjà dans le modèle** | faible, config = une liste ordonnée |
|
||||
| **Avant / après** | « À quoi ressemblait cette place en 1900 ? » — le visiteur devine, puis bascule | **`BeforeAfterPairs`** du lot 9 du Studio | rendu seul |
|
||||
|
||||
**Le meilleur rapport valeur/effort est « Répondre »** : `SectionQuiz` est déjà configuré par les
|
||||
clients aujourd'hui. Le jeu, c'est le rendu — zéro donnée nouvelle, zéro apprentissage côté client.
|
||||
|
||||
**Le plus intéressant commercialement est « Trouver »**, pour une raison qui n'a rien à voir avec la
|
||||
VR : il fonctionne sur un pano 2D pivotant en web. Une mécanique de jeu qui se vend **sans casque**,
|
||||
sur l'add-on immersif seul.
|
||||
|
||||
**Écarté, et pourquoi :**
|
||||
|
||||
| Idée | Pourquoi non |
|
||||
|---|---|
|
||||
| Remontage d'objet (amphore à reconstituer) | Effet musée énorme, mais il faut un GLB **pré-découpé en pièces**. Le client ne peut pas le produire seul → casse la règle d'autonomie. **Sur devis uniquement** |
|
||||
| Escape game VR | La logique conditionnelle n'est pas configurable en trois champs. L'escape game reste sur le canal mobile, où il fonctionne déjà |
|
||||
| Tir, action, visée | Hors sujet produit |
|
||||
| Dialogue avec un PNJ scripté | Le guide IA le fait déjà mieux, et sans script à maintenir |
|
||||
| Tout ce qui demande de marcher | Contredit le roomscale stationnaire (§3) |
|
||||
|
||||
---
|
||||
|
||||
## 10. Ce que ce document change dans les deux autres plans
|
||||
|
||||
| Plan | À reprendre |
|
||||
|---|---|
|
||||
| `studio-plan.md` | Le **lot 11 (3D)** passe de quatre lignes à un lot réel : `Scene3D` comme `GenerationKind`, World Labs dans le catalogue, provenance obligatoire sur `Model3D`. Les décisions n°1, 4, 5 et 6 du §5 ci-dessus touchent des lots **antérieurs** (lot 0, lot 1, lot 3) et doivent y être écrites. |
|
||||
| `vr-quest-unity-plan.md` | Le **§9 (POI sur GLB)** gagne la version de modèle, l'invalidation des POI et la décision « éditeur en iframe three.js ». Le **§6 (pricing)** gagne l'enveloppe de stockage chiffrée. Le §2 lot V-4 gagne `ImmersiveBackground` comme source du fond de scène. |
|
||||
| `todo-features.md` | La « Ressource 360° » devient les **trois** valeurs d'enum, en une migration. |
|
||||
| Kanban | Les cartes 250, 280, 300, 320 et 330 restent valides. Ce document est la source à citer en `src:` pour la frontière. |
|
||||
@ -116,7 +116,7 @@ Tout sur `Instance`, dupliqué depuis `SubscriptionPlan` : `StorageQuotaBytes`,
|
||||
|---|---|---|
|
||||
| 1 | Portée de l'identité visuelle | **Une par instance** (le musée) + **surcharge optionnelle par configuration** (parcours thématique, ex. Halloween). Cohérent avec `Configuration.PrimaryColor/SecondaryColor/Languages` qui existent déjà |
|
||||
| 2 | Souveraineté | **Champ de configuration déclaratif** pour l'instant. La couche fournisseur rend le changement possible sans réécriture ; pas de chantier stockage EU aujourd'hui |
|
||||
| 3 | Crédits | **Monnaie dédiée**, distincte des tokens IA. Griller son quota d'images ne doit pas priver les visiteurs du guide IA |
|
||||
| 3 | Crédits | **Monnaie dédiée**, distincte des tokens IA. Griller son quota d'images ne doit pas priver les visiteurs du guide IA. **Révisé le 2026-09-11 : crédits rechargeables à expiration 12 mois, pas de quota mensuel** — voir §3.5 |
|
||||
| 4 | Rôle valideur | **Permission détachée** (`Manager.assetvalidation`), pas un 5e rôle. Accordée d'office à `InstanceAdmin`, activable sur un `ContentEditor` |
|
||||
| 5 | Brouillons | **Crédits débités toujours** (l'appel a coûté). **Quota stockage compté seulement à la validation.** Variantes non retenues supprimées à la fermeture du panneau ; balayage Hangfire à 30 j comme filet |
|
||||
| 6 | Mention IA | **Pas de gravure dans les pixels par défaut** — irréversible, et laid sur une illustration de musée. Provenance en base + badge UI visiteur dans les langues du projet + métadonnées fichier. Gravure disponible en **option par instance** pour l'institution qui l'exigerait par écrit |
|
||||
@ -534,28 +534,57 @@ onglet fermé, navigateur planté. Précédents en place : `AuditLogPurgeService
|
||||
### 3.5 Crédits et garde-fous
|
||||
|
||||
```
|
||||
SubscriptionPlan += HasStudio, ImageCreditsPerMonth
|
||||
Instance += StudioEnabled, ImageCreditsPerMonth, ImageCreditsThisMonth,
|
||||
ImageCreditsMonthKey, ImageCreditsHardCap,
|
||||
StudioPerUserDailyCap, StudioProviderRegion
|
||||
SubscriptionPlan += HasStudio, StudioCreditsGranted -- dotation à la souscription
|
||||
Instance += StudioEnabled, StudioCreditsBalance, StudioCreditsExpireAt,
|
||||
StudioCreditsHardCap, StudioPerUserDailyCap, StudioProviderRegion
|
||||
|
||||
CreditLedger (append-only, exportable CSV)
|
||||
Id, InstanceId, UserId, GenerationJobId?, Kind, Amount, BalanceAfter,
|
||||
ModelKey, CreatedAt, Note
|
||||
Kind: Reserve | Charge | Refund | Grant | MonthlyReset
|
||||
Kind: Reserve | Charge | Refund | Grant | Expire
|
||||
```
|
||||
|
||||
> **Révisé le 2026-09-11 — deux changements, tous deux gratuits maintenant et coûteux après la
|
||||
> première migration.**
|
||||
>
|
||||
> **a) `ImageCredits*` → `StudioCredits*`.** Une 3D coûte 10 à 50 fois une image, et un monde généré
|
||||
> n'est pas une image du tout. Le nom `ImageCredits` aurait menti dès le lot 11. `GenerationModel.CreditCost`
|
||||
> porte déjà le coût par modèle : rien d'autre à changer côté tarification.
|
||||
>
|
||||
> **b) Crédits rechargeables à expiration 12 mois, au lieu d'un quota mensuel.** Le reset mensuel
|
||||
> suppose un usage linéaire. **Un musée ne travaille pas comme ça** : il génère 200 images en trois
|
||||
> semaines pour préparer une expo, puis rien pendant cinq mois. Un forfait mensuel se gaspille dix mois
|
||||
> sur douze — le client a le sentiment de payer pour rien, et la capacité provisionnée ne sert pas.
|
||||
> Le modèle rechargeable est aligné sur l'usage réel *et* sur un coût qui est à l'acte.
|
||||
>
|
||||
> ➡️ Disparaissent : `ImageCreditsPerMonth`, `ImageCreditsThisMonth`, `ImageCreditsMonthKey`, et le
|
||||
> `Kind: MonthlyReset`. Apparaissent : `StudioCreditsBalance`, `StudioCreditsExpireAt`, et un
|
||||
> `Kind: Expire` pour tracer la péremption dans le journal. **Le `CreditLedger` encaisse le modèle
|
||||
> sans changement de structure** — il était déjà append-only avec un `Kind: Grant`.
|
||||
>
|
||||
> ⚠️ **Reste ouvert** : la recharge côté Stripe. Le webhook ne gère que `checkout.session.completed`
|
||||
> et `invoice.payment_failed` (`StripeWebhookController.cs:62-65`), rien sur les lignes d'abonnement.
|
||||
> Un achat de crédits est un paiement ponctuel, donc `checkout.session.completed` suffit — mais le
|
||||
> mapping session → `Kind: Grant` est à écrire. Pour les premiers clients, un `Grant` posé à la main
|
||||
> depuis l'écran SuperAdmin suffit.
|
||||
>
|
||||
> **Le critère qui sépare les deux monnaies**, pour ne plus se reposer la question : *consommé en
|
||||
> temps réel par le visiteur* (chat, vocal → quota IA, reset mensuel, attribut du palier) contre
|
||||
> *produit une fois par le client* (images, 3D, scènes, vidéo, **TTS pré-généré** → crédits Studio,
|
||||
> rechargeables, add-on). Détail et vérification dans le code :
|
||||
> [immersif-frontiere-plan.md](immersif-frontiere-plan.md) §2bis.
|
||||
|
||||
**Le plafond dur n'est pas le bon outil contre le stagiaire.** Le scénario « vider un budget en une
|
||||
après-midi » est un problème **par utilisateur**, pas par organisation : le budget du mois est
|
||||
justement là pour être dépensé sur le mois. Deux garde-fous distincts :
|
||||
|
||||
- `ImageCreditsHardCap` — plafond organisation que même un dépassement facturé ne franchit pas.
|
||||
- `StudioCreditsHardCap` — plafond organisation que même un dépassement facturé ne franchit pas.
|
||||
- `StudioPerUserDailyCap` — le vrai rempart : N générations par utilisateur et par jour.
|
||||
|
||||
**Réservation en deux temps.** `CheckQuota` avant / incrément après suffit à un appel LLM bloquant de
|
||||
2 s. Il ne suffit pas à dix jobs Hangfire de 40 s lancés en parallèle : les dix contrôles passent avant
|
||||
le premier débit. Donc : `Reserve` à l'enqueue, `Charge` à la complétion (ajusté au coût réel),
|
||||
`Refund` à l'échec. Solde disponible = `ImageCreditsPerMonth − (charges + réservations ouvertes)`.
|
||||
`Refund` à l'échec. Solde disponible = `StudioCreditsBalance − réservations ouvertes`.
|
||||
|
||||
Le **coût estimé** vient de `GenerationModel.CreditCost × VariantCount`, affiché avant le lancement.
|
||||
Le **journal exportable** est une projection CSV de `CreditLedger` — c'est le document que les
|
||||
@ -1154,10 +1183,10 @@ Une migration, additive, aucune donnée existante touchée — sauf `GuidedStep`
|
||||
|
||||
```
|
||||
Resource += AiProvenance jsonb?
|
||||
Instance += StudioEnabled, ImageCreditsPerMonth, ImageCreditsThisMonth,
|
||||
ImageCreditsMonthKey, ImageCreditsHardCap,
|
||||
StudioPerUserDailyCap, StudioProviderRegion, IsAiWatermarkBurned
|
||||
SubscriptionPlan += HasStudio, ImageCreditsPerMonth
|
||||
Instance += StudioEnabled, StudioCreditsBalance, StudioCreditsExpireAt,
|
||||
StudioCreditsHardCap, StudioPerUserDailyCap, StudioProviderRegion,
|
||||
IsAiWatermarkBurned
|
||||
SubscriptionPlan += HasStudio, StudioCreditsGranted
|
||||
User += CanValidateAssets
|
||||
VisitorQuestion += PersonaId? -- sans lui, les stats restent agrégées sur un
|
||||
-- assistant imaginaire : impossible de voir qu'un
|
||||
@ -1219,7 +1248,8 @@ compression serveur 2560/q82, ajout de `LB`.
|
||||
### Lot 1 — Crédits
|
||||
|
||||
`CreditLedger`, colonnes `Instance`/`SubscriptionPlan`, réserve/charge/remboursement, `GET /credits`,
|
||||
export CSV. Troisième jauge dans le pied de menu + popover au clic ; détail et journal dans
|
||||
export CSV. **Crédits rechargeables à expiration, pas de reset mensuel** (§3.5) : le balayage de
|
||||
péremption est un job Hangfire, précédents en place (`AuditLogPurgeService`). Troisième jauge dans le pied de menu + popover au clic ; détail et journal dans
|
||||
**Abonnement**. Corriger au passage le gating de l'entrée Abonnement (`main_screen.dart:547-550`),
|
||||
aujourd'hui réservée à `plan-essentiel`. Testable seul, sans aucun appel fal.ai.
|
||||
|
||||
@ -1291,6 +1321,15 @@ animé, sous une forme qui tient en 2026.
|
||||
Meshy 6 / Tripo, objets isolés, export GLB, `ResourceType.Model3D`. Suppose un viewer GLB côté
|
||||
visiteur — dépend du chantier VR/XR (`vr-quest-unity-plan.md`).
|
||||
|
||||
⚠️ **Ce lot faisait quatre lignes et se contentait de renvoyer au plan VR, qui lui-même renvoyait
|
||||
ici.** La frontière est tranchée depuis le 2026-09-11 dans
|
||||
[immersif-frontiere-plan.md](immersif-frontiere-plan.md), qui ajoute : `Scene3D` comme
|
||||
`GenerationKind` (World Labs / Marble, API depuis janvier 2026, ~0,12 $ le monde draft),
|
||||
provenance **obligatoire et non désactivable** sur un `Model3D` généré, `ProviderResult`
|
||||
multi-fichier, et surtout **cinq décisions qui touchent des lots antérieurs à celui-ci** — dont le
|
||||
pipeline d'ingestion unique (lot 0) et le renommage des crédits (lot 1). Les lire avant d'écrire
|
||||
la première migration du Studio, pas en arrivant au lot 11.
|
||||
|
||||
**Le test de réussite se joue à la fin du lot 4.** Si à ce stade un conservateur ne produit pas
|
||||
10 images cohérentes seul, les lots suivants n'y changeront rien.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user