From fb1d15d0b3775668c54c11e176c552db2530e033 Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Wed, 16 Sep 2026 15:29:16 +0200 Subject: [PATCH] =?UTF-8?q?Tags=20NFC=20:=20analyse=20du=20troisi=C3=A8me?= =?UTF-8?q?=20d=C3=A9clencheur=20physique?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deux recadrages par rapport à la demande initiale : le déclencheur n'est pas un POI (qui est un point sur un GLB) mais une Section, au même endroit que le beacon ; et l'indirection code → section n'a aucun équivalent existant à réutiliser — en v1 le tag porte la même URL que le QR, donc zéro entité, zéro endpoint. Le vrai coût est ailleurs : ni Universal Links ni App Links n'existent sur nos domaines, et ce lot-là profite autant au QR, qu'un appareil photo natif n'ouvre pas dans l'app aujourd'hui. Dépend du déploiement de visitapp-web pour le fallback sans app installée. Carte kanban 265. Co-Authored-By: Claude Opus 5 (1M context) --- ...-tags-nfc-comme-declencheurs-de-section.md | 13 +++++ status/roadmap-canaux.md | 1 + v2/nfc-triggers-plan.md | 54 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 kanban/cards/5-planifie/265-tags-nfc-comme-declencheurs-de-section.md create mode 100644 v2/nfc-triggers-plan.md diff --git a/kanban/cards/5-planifie/265-tags-nfc-comme-declencheurs-de-section.md b/kanban/cards/5-planifie/265-tags-nfc-comme-declencheurs-de-section.md new file mode 100644 index 0000000..68a277a --- /dev/null +++ b/kanban/cards/5-planifie/265-tags-nfc-comme-declencheurs-de-section.md @@ -0,0 +1,13 @@ +--- +title: Tags NFC comme déclencheurs de section +area: backend manager visitapp +horizon: v2 +tags: visitapp, matériel +flag: warn | Nouveau 16/09 · le gros du coût est les Universal/App Links, partagés avec le QR +src: nfc-triggers-plan.md · ScannerDialog.dart:31-38 · Section.cs:57 · main.dart:69 +--- +

Troisième déclencheur physique, à côté du QR et du beacon. Analyse et faisabilité : v2/nfc-triggers-plan.md.

+

⚠️ Deux recadrages par rapport à la formulation initiale. (1) Le déclencheur n'est pas un « POI » : dans MyInfoMate le POI est un point posé sur un GLB (VR/3D, immersif-frontiere-plan.md). Le déclencheur physique est une SectionSection.IsBeacon / BeaconId, lu par geo_beacon_trigger_service.dart:177. Le tag NFC se branche au même endroit que le beacon. (2) L'URL /t/{instanceId}/{code} et sa table de mapping n'ont pas d'équivalent existant à réutiliser : les QR d'aujourd'hui portent l'id de section directement dans l'URL (trois formats coexistants, ScannerDialog.dart:31-38), il n'y a aucun endpoint de résolution code → section. v1 = le tag porte la même URL que le QR, donc zéro entité, zéro endpoint, zéro CRUD ; l'indirection ne se justifie que si un client demande un parc de tags réassignables — et elle vaut bien moins qu'en QR, puisque réécrire un NTAG prend deux secondes alors qu'un QR se réimprime.

+

Le vrai coût est ailleurs : les Universal Links (iOS) et App Links (Android) n'existent pas. Aucun assetlinks.json ni apple-app-site-association sur nos domaines (le seul du workspace est dans OpenGlasses, qui n'est pas à nous), et app_links n'est branché que sur le retour de deep link Meta AI (main.dart:69). ✅ Ce lot bénéficie autant au QR : aujourd'hui un QR scanné par l'appareil photo natif n'ouvre pas l'app.

+

Dépendance : le fallback web d'un tag scanné sans app installée, c'est visitapp-webpas encore déployé (carte « Déployer le visiteur web »). Sans lui, un tag scanné par un visiteur sans l'app tombe dans le vide.

+

Ce qui ne marchera pas, à dire au commercial : pas de lecture NFC depuis visitapp-web (WebNFC est Chrome/Android uniquement, jamais Safari), et l'écriture de tags depuis iOS est trop contrainte — l'écran admin de programmation sera Android-only. En contrepartie, iPhone XS+ lit un tag NDEF sans aucune app, ce qui est l'argument réel du canal.

diff --git a/status/roadmap-canaux.md b/status/roadmap-canaux.md index ce3b73a..c3c53b5 100644 --- a/status/roadmap-canaux.md +++ b/status/roadmap-canaux.md @@ -24,6 +24,7 @@ Plans détaillés, pas encore démarrés en dev (sauf mention contraire) : | AI Persona par venue (guide IA personnalisable) | [v2/myinfomate-ai-persona-analysis.md](../v2/myinfomate-ai-persona-analysis.md) | Architecture de référence pour les chantiers IA ci-dessus | | Lunettes Ray-Ban Meta | [roadmap.md](../roadmap.md) (section XR), [rayban-meta-integration.md](../rayban-meta-integration.md) | 🔨 **POC fonctionnel — bien plus avancé que ce que cette ligne disait jusqu'au 2026-08-09.** Voir §5bis | | VR Meta Quest (borne office tourisme) | [v2/vr-quest-unity-plan.md](../v2/vr-quest-unity-plan.md) · [roadmap.md](../roadmap.md) (section XR) | 📦 **V2** — ⚠️ **« zéro ligne de code » était faux** (corrigé le 2026-08-31, relevé dans le code). Le canal VR est déjà dans le modèle : `AppType.VR`, `Instance.IsVR` en base depuis juillet 2025, sous-menu « VR » branché dans `main_screen.dart:65`, filtre stats + i18n `statsChannelVR` prêts. **Ce qui manque** : l'écran de flotte (`main_screen.dart:704` = `Text("TODO vr")`), un `Device.AppType` (le `DeviceController` est hardcodé sur `Tablet`), et l'app Unity. Back-office XR : **8-12 j**. App Unity : **3-4 mois**. La landing annonce « Meta Quest — Bientôt » en 4 langues (`translations.ts`, clé `mode4Desc`) | +| Tags NFC (déclencheur de section) | [v2/nfc-triggers-plan.md](../v2/nfc-triggers-plan.md) | 📦 **V2** — analysé dans le code le 2026-09-16. Troisième déclencheur physique à côté du QR et du beacon. ⚠️ **Le coût n'est pas le NFC** : les **Universal Links / App Links n'existent pas** (aucun `assetlinks.json` ni `apple-app-site-association`, `app_links` branché seulement sur le retour Meta AI, `main.dart:69`) — ce lot-là **sert aussi au QR**, qui aujourd'hui n'ouvre pas l'app quand il est scanné par l'appareil photo natif. Le tag porte **la même URL que le QR** : aucune entité, aucun endpoint de résolution en v1. Dépend du **déploiement de `visitapp-web`** pour le fallback sans app. 4-7 j | | Canal subsides | [plan-import-ia-stats-subsides.md](../plan-import-ia-stats-subsides.md) | Actions administratives/réseau, pas de dev | --- diff --git a/v2/nfc-triggers-plan.md b/v2/nfc-triggers-plan.md new file mode 100644 index 0000000..a1943b3 --- /dev/null +++ b/v2/nfc-triggers-plan.md @@ -0,0 +1,54 @@ +# Tags NFC comme déclencheurs de section + +> Chantier **V2**, **analysé dans le code le 2026-09-16** à partir d'une spec d'intention. +> Carte kanban : `cards/5-planifie/265-…` +> Ce document **corrige la spec d'origine sur deux points de réalité** (le mot « POI », et +> le schéma d'URL avec table de mapping), puis dit comment on le fait. + +--- + +## Ce que la spec d'origine supposait, et ce que dit le code + +| Hypothèse de la spec | Réalité relevée | +|---|---| +| « Déclencher un **POI** » | Dans MyInfoMate, un **POI est un point posé sur un GLB** (3D/VR — voir `immersif-frontiere-plan.md` §9). Le déclencheur physique d'un contenu, c'est une **`Section`** : `Section.IsBeacon` / `Section.BeaconId` (`Section.cs:57`), lue côté visiteur par `geo_beacon_trigger_service.dart:177` et `configuration_page.dart:205`. Le NFC se branche **au même endroit que le beacon**, pas ailleurs | +| « Réutiliser l'endpoint de résolution des QR, s'ils utilisent déjà une URL de ce format » | **Il n'y en a aucun.** Les QR portent l'id de section **directement dans l'URL**, et trois formats coexistent sur le terrain (`ScannerDialog.dart:31-38`) : `app.myinfomate.be/download/{instanceId}/{configId}/{sectionId}`, `web.mymuseum.be/{instanceId}/{configId}/{sectionId}` (déjà imprimé, MDLF), et un **id de section brut** (déjà imprimé, Fort Saint-Héribert). Il n'y a donc rien à réutiliser : l'entité « tag », le code opaque et l'endpoint `code → section` seraient **du neuf intégral** | +| « Déclarer les URLs en Universal Links / App Links » | **Rien n'existe.** Aucun `assetlinks.json` ni `apple-app-site-association` sur nos domaines (le seul du workspace est dans `OpenGlasses`, qui n'est pas à nous). `app_links` est bien au `pubspec.yaml:89` mais branché **uniquement sur le retour de deep link Meta AI** (`main.dart:69` → `MetaGlassesService.handleDeepLink`), et `AndroidManifest.xml` n'a pas d'intent-filter `autoVerify` sur un domaine http | +| « Si l'app n'est pas installée, l'URL affiche une page web utile » | `visitapp-web` fait exactement ça (`app.myinfomate.be/[slug]`), mais **il n'est pas déployé** — il manque le Dockerfile et l'entrée dans le compose (carte « Déployer le visiteur web »). Le fallback est une **dépendance**, pas un acquis | + +--- + +## Décisions + +| Décision | Conséquence | +|---|---| +| **1. Le tag porte la même URL que le QR** | Pas d'entité `NfcTag`, pas de code opaque, pas d'endpoint de résolution, pas de CRUD manager. Le mapping tag → section, c'est l'URL écrite sur le tag. **Zéro ligne de backend pour la v1** | +| **2. L'indirection `code → section` est reportée, pas refusée** | L'argument « réassigner sans réécrire le tag » est réel, mais il vaut **beaucoup moins en NFC qu'en QR** : réécrire un NTAG prend deux secondes avec un téléphone, alors qu'un QR se réimprime, se replastifie et se recolle. On ouvrira l'indirection le jour où un client gère un parc de tags — et ce jour-là elle devra couvrir **QR et NFC ensemble**, pas le NFC seul | +| **3. Le lot utile est celui des liens, pas celui du NFC** | Universal Links + App Links + routage du deep link entrant vers la section. ✅ **Le QR en bénéficie autant** : aujourd'hui un QR scanné par l'appareil photo natif n'ouvre pas l'app, il ouvre le navigateur. C'est ce lot qui porte la valeur, le NFC n'en est qu'un second émetteur | +| **4. Lecture in-app en fallback seulement** | `nfc_manager` derrière le bouton Scanner existant (`ScannerBouton.dart`), à côté du QR. Le cas nominal reste **le tag lu sans ouvrir l'app** — c'est tout l'intérêt du canal | +| **5. Écran de programmation des tags : Android-only** | L'écriture NDEF depuis iOS est trop contrainte pour un outil de terrain, et le public visé est **l'admin qui pose les tags**, pas le visiteur. Un seul appareil de programmation suffit à un lieu | +| **6. Verrouillage en écriture : hors v1** | Irréversible, donc une erreur de pose coûte le tag. À ouvrir après un vrai déploiement, avec double confirmation | +| **7. Pas de lecture par UID** | Confirmé : l'UID n'est pas réassignable et impose une table de correspondance — donc tous les inconvénients de la décision 2 sans son bénéfice | + +--- + +## Ce qui ne marchera pas — à savoir avant de le vendre + +- **Aucune lecture NFC sur `visitapp-web`.** WebNFC est Chrome/Android uniquement, jamais Safari. Le plan **Essentiel étant web-only**, le NFC ne s'y vend pas comme « scan dans l'app » — il s'y vend comme « on approche le téléphone, une page s'ouvre », ce qui est vrai et ne demande rien de plus que la décision 1. +- **iPhone 7 / 8 / X** ne lisent pas les tags en arrière-plan : il leur faut l'app ouverte. iPhone **XS et plus** lisent un NDEF sans aucune app installée — c'est l'argument commercial réel, et il est bon. +- **Un tag à plat sur du métal ne se lit pas.** Prévoir des tags sur mousse ou des NTAG « on-metal » ; le raccourci du bois transparent au BLE (carte beacons) n'a pas d'équivalent ici. +- **Le NFC ne remplace pas le beacon** : il demande un geste volontaire à 1-2 cm, il ne déclenche rien à l'approche. Les trois déclencheurs se cumulent, ils ne se substituent pas. + +--- + +## Découpage + +| Lot | Contenu | Estimation | +|---|---|---| +| **A — Liens universels** (le seul indispensable) | `assetlinks.json` + `apple-app-site-association` servis sur le domaine, intent-filter `autoVerify` + capability Associated Domains, routage du deep link entrant vers la section (logique partagée avec le parsing de `ScannerDialog`, à extraire du dialogue). **Bénéficie au QR dès la livraison** | 2-3 j | +| **B — NFC** | Permission et intent-filter NDEF Android, capability NFC Tag Reading + `NFCReaderUsageDescription` + entitlement iOS, `nfc_manager` derrière le bouton Scanner | 1-2 j | +| **C — Écran de programmation admin** | Choisir une section → approcher un tag → écrire l'URL NDEF. Android-only, NTAG213/215/216 | 1-2 j | +| **D — Fallback web** | Rien à écrire : c'est le déploiement de `visitapp-web`. **Dépendance externe** | — | +| *(reporté)* **E — Indirection `code → section`** | Entité, CRUD manager, endpoint de résolution — et alors **pour QR et NFC ensemble** | 3-4 j | + +**Total v1 (A+B+C) : 4-7 jours**, dont A porte à lui seul la moitié de la valeur et sert déjà au QR.