diff --git a/HANDOFF-LIVE-BACKEND.md b/HANDOFF-LIVE-BACKEND.md new file mode 100644 index 0000000..06e98e5 --- /dev/null +++ b/HANDOFF-LIVE-BACKEND.md @@ -0,0 +1,101 @@ +# Handoff — Backend `/live` (Mac → session Linux `coach_sportif`) + +**De** : Claude Code Mac mini, 2026-05-25 (chantier watchOS Live Workout). +**Pour** : session Claude Code sur le repo `coach_sportif` (backend FastAPI + templates). +**Objet** : finir le **point 1** — la page `/live` doit s'afficher dans l'app et +recevoir les samples temps réel poussés par la Watch. + +## Contexte : le natif est TERMINÉ et PROUVÉ + +Phases 1-3 (target watchOS `CoachWatch` + 4 fichiers Swift + plugin Capacitor +`CoachLiveBridge`) livrées sur `coach-ios` (commits `5d60a40` → `678b5a4`). + +**Pont watch → iPhone validé end-to-end sur simulateur** (paire iPhone+Watch) : +les logs montrent chaque sample envoyé par la Watch reçu à l'identique par le +plugin iPhone (HR 130.69 → 148.32, latence ~300 ms). Donc dès que `/live` +s'affiche dans l'app et écoute l'event, **les chiffres défileront**. + +Un **mode Test (FC simulée)** existe dans l'app watch (bouton sous les activités) : +il envoie des samples synthétiques **sans HealthKit**. → tu peux valider `/live` +**sans** dépendre de la vraie FC (la Santé de la Watch physique de Sylvain a un +bug système séparé, hors scope ici). + +## Le problème observé + +En ouvrant `/live` dans l'app, la page renvoie **« token invalide »**. +→ La route `/live` ne reconnaît pas la session authentifiée de l'app. + +Rappel : l'app (wrapper Capacitor) s'authentifie via **injection de cookie de +session dans `AppDelegate`** (coach-ios). Toutes les pages authentifiées marchent +via ce cookie. La route `/live` (Phase 4) avait été écrite avec +`check_auth(request, token)` où `token` venait d'un `?token=` — ce qui ne matche +pas le flux cookie de l'app. + +## À faire côté `coach_sportif` + +### 1. Auth de `/live` = même mécanisme que les autres pages authentifiées +Faire en sorte que `/live` accepte la **session/cookie** de l'app (comme les +autres routes protégées), `?token=` restant un fallback optionnel. Concrètement : +utiliser le même `Depends`/helper d'auth que les autres pages, au lieu d'exiger +le token en query. Objectif : ouvrir `/live` dans l'app authentifiée → 200, pas +« token invalide ». + +### 2. Un accès à `/live` depuis l'UI web +Ajouter un lien/bouton vers `/live` dans la nav de l'app (là où c'est pertinent — +ex. page séance / accueil), pour que l'utilisateur y arrive sans taper d'URL. + +### 3. JS du template `live_workout.html` — contrat EXACT du plugin natif + +Le plugin iPhone émet l'event **`liveSample`** (jsName du plugin : +**`CoachLiveBridge`**). Champs d'un sample : + +| champ | type | sens | +|---|---|---| +| `heartRate` | number | FC en bpm | +| `activeEnergyKcal` | number | calories actives cumulées | +| `distanceMeters` | number | distance cumulée en mètres | +| `elapsedSec` | number | durée écoulée en secondes | +| `ts` | number | timestamp epoch (secondes, fractionnaire) | +| `sim` | bool | présent (=true) uniquement en mode Test | + +JS à mettre dans le template (page chargée DANS l'app Capacitor) : + +```html + +``` + +> Vérifier que `/static/vendor/capacitor-core.js` (ou équivalent) expose bien +> `registerPlugin`. En navigateur pur (hors app) il n'y a aucun WCSession donc 0 +> sample — c'est normal, la page n'est utile que dans le wrapper iOS. + +## Test d'acceptation (sans device, sur simulateur) + +1. App iOS (sim ou device) sur `/live`, page au premier plan. +2. App watch → bouton **Test (FC simulée)**. +3. `/live` doit afficher FC/calories/distance/durée qui défilent (~ toutes les 2 s) + et le statut « En direct ». + +Côté natif c'est déjà prouvé (plugin `CoachLiveBridge` logue +`liveSample reçu de la Watch hr=…`). Si `/live` ne bouge pas alors que ce log +apparaît, c'est le JS/registerPlugin du template à corriger. + +## Hors scope de ce handoff +- Vraie FC sur la Watch physique de Sylvain (bug système Santé de SA montre — + NanoSettings crashe, à régler par désappairage/réappairage). +- TestFlight (signing/App Store Connect côté Sylvain). diff --git a/docs/watchos-live-workout-plan.md b/docs/watchos-live-workout-plan.md index 626a5a6..79f8c50 100644 --- a/docs/watchos-live-workout-plan.md +++ b/docs/watchos-live-workout-plan.md @@ -477,10 +477,19 @@ UI picker rendue. 3. Enregistrement plugin Capacitor 8 = `bridge?.registerPluginInstance(...)` dans `capacitorDidLoad()` (PAS la macro `CAP_PLUGIN`), CAPBridgedPlugin. -### Reste à faire +### Pont watch -> iPhone PROUVÉ E2E (simulateur, 2026-05-25) -- **Test device** (FC réelle, WatchConnectivity → /live) : nécessite l'Apple - Watch physique + signing (impossible en simulateur, pas de FC réelle). -- **Cross-check** : la page `/live` déployée doit utiliser `registerPlugin('CoachLiveBridge')` - et lire `heartRate / activeEnergyKcal / distanceMeters / elapsedSec / ts`. -- TestFlight interne. +Validé sur paire simulée iPhone+Watch (mode Test FC simulée + hook env `AUTOSIM`) : +chaque sample envoyé par la Watch (`sendSample … hr=130.69→148.32`) est reçu à +l'identique par le plugin iPhone (`liveSample reçu … hr=130.69→148.32`), latence +~300 ms. Vue live watch rendue (FC/calories/distance). Toute la chaîne native +fonctionne ; il ne reste que l'affichage web et la vraie FC. + +### Reste à faire — 2 blocages EXTERNES (pas le code natif) + +1. **Backend `/live`** (« token invalide ») : route à passer en auth cookie de + session + lien d'accès depuis l'app + JS template. Détail + contrat exact dans + **`HANDOFF-LIVE-BACKEND.md`** (repo `coach_sportif`, session Linux). +2. **Vraie FC sur la Watch physique de Sylvain** : bug système Santé de SA montre + (NanoSettings crashe, Santé spinne) — désappairer/réappairer la Watch. +3. TestFlight interne (signing / App Store Connect).