docs(ideai): mémoire client online, clôture ticket #64, cadrage #65-#70

Ajoute les notes mémoire d'architecture, de philosophie de la couche
online et d'UX pour le client online, clôture le ticket #64, reflète
les tickets #46/#54/#57/#62, ajoute le cadrage des tickets #65 à #70.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-19 21:25:57 +02:00
parent e60c8bbdb8
commit 53b4957bc6
28 changed files with 910 additions and 37 deletions

View File

@ -1,6 +1,6 @@
---
issueRef: "#46"
version: 6
updatedBy: {"kind":"user"}
updatedAt: 1784482343900
version: 7
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
updatedAt: 1784488112374
---

View File

@ -2,15 +2,15 @@
id: "dda499ac-7197-4321-bd2b-a303510b1bbe"
number: 46
title: "Créer un serveur headless pour l'application"
status: "open"
status: "qa"
priority: "low"
sprint: "4237adfd-91eb-45ff-9f32-6ce1daa39822"
links: []
agentRefs: [{"agentId":"57695b92-24d0-4876-837c-76116e70a6ae","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
createdAt: 1784379695135
updatedAt: 1784482343900
version: 6
updatedAt: 1784488112374
version: 7
---
J'aimerais que l'application puisse proposer des services online aussi. Un peu a la manière de Heavy avec la possibilité de partager ses séances etc. A la manière de Heavy, j'aimerais que l'on puisse se créer un compte et s'y connecter, synchroniser son historique de seances, ses séances, ses programmes ainsi que ses exercices. Ce ticket est la partie serveur/web API, il faudra que ça soit un serveur headless linux qui tourne dans un container docker. Il faudra que je puisse y acceder via un reverse proxy qui tourne sur une machine différente de celle du serveur headless mais dans le même réseau local. J'y accederais via une adresse https. le container se lancera ensuite à partir d'un docker-compose.yaml dans lequel tu laissera les champs libre de tout ce qui sera necessaire de configurer (adresse ip du reverse proxy, de la machine sur laquelle tourne le docker si necessaire etc.). Pour la création du serveur, créé un subdirectory spécialement pour cette partie serveur. Dans le dossier serveur à lma racine, je veux un script pour pouvoir push le container sur le gitea qui est déjà lié au projet, je veux aussi le docker-compose.yaml demandé.

View File

@ -1,6 +1,6 @@
---
issueRef: "#54"
version: 4
updatedBy: {"kind":"user"}
updatedAt: 1784451193831
version: 5
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
updatedAt: 1784487430850
---

View File

@ -2,15 +2,15 @@
id: "7e6894d5-36ad-413b-9fda-be3ba26db6cb"
number: 54
title: "Exercice à plusieurs étapes"
status: "open"
status: "qa"
priority: "medium"
sprint: "1bb8bdf2-9c35-4f53-9a31-1390a47bec63"
links: []
agentRefs: [{"agentId":"57695b92-24d0-4876-837c-76116e70a6ae","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
createdAt: 1784449895047
updatedAt: 1784451193831
version: 4
updatedAt: 1784487430850
version: 5
---
Dans certains exercices, il peut être interessant qu'il y ai plusieurs étapes. Par exemple, pour un exercice de dribble, il peut être interessant de dire "dribbler main droite pendant 10 sec, puis dribller main gauche pendant 10 secondes, effectuer un double pas et réaliser 10 pompes" par exemple. Le tout représente alors une répétition mais se décompose en 4 étapes avec deux étapes qui se base sur un temps, et deux étapes sur un nombre de répétitions. J'aimerais donc pouvoir définir des étapes pour chaque exercice. L'ensemble de toutes les étape de l'exercice forme une répetition d'une série. Comme pour une série, chacune des étape doit pouvoir avoir un temps à définir (avec une valeur par défaut obligatoire > 0) ou un nombre de répétitions. Dans le cas d'une étape avec un temps, un chronometre est lancé. Dans les 3 dernieres secondes, un bip retenti pour chaque seconde et quand le temps arrive à 0 le bip est plus long que les autres. dans le cas ou deux étapes avec un temps s'enchainent, le second chronometre part directement à la fin de l'etape précédent. Le but est d'enchainer les étapes, il n'y a pas de pauses entre les différentes étapes. On eput aussi proposer de renseigner un score pour chaque étape de la même façon que pour les série.

View File

@ -1,6 +1,7 @@
---
issueRef: "#57"
version: 4
updatedBy: {"kind":"user"}
updatedAt: 1784482343900
version: 6
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
updatedAt: 1784488107329
---
Mémoire IdeA écrite par Main : `gametime-online-layer-philosophy`. Couvre : connexion toujours optionnelle, aucune interruption/popup si le serveur est indisponible, principe "le serveur sert l'app, jamais l'inverse" (adapter le schéma serveur aux changements client, ex. étapes d'exercice du chantier #54), et la liste de ce qui doit rester en cache local (profil, pseudo, photo, stats futures) pour un affichage toujours cohérent hors ligne. Cette mémoire est référencée pour les tickets futurs (#63 et suite).

View File

@ -2,15 +2,15 @@
id: "d5b0bd7e-a021-4824-a278-b2e9c14a1cf6"
number: 57
title: "Allimenter la mémoire projet pour l'UI online de l'app"
status: "open"
status: "closed"
priority: "medium"
sprint: "4237adfd-91eb-45ff-9f32-6ce1daa39822"
links: []
agentRefs: [{"agentId":"57695b92-24d0-4876-837c-76116e70a6ae","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
createdAt: 1784481519943
updatedAt: 1784482343900
version: 4
updatedAt: 1784488107329
version: 6
---
L'application aura donc une couche online. L'application se veut cependant rester un maximum offline sur les ofnctionnalités de base. Je veux que cette couche online soit le plus transparente possible pour l'utilisateur. En clair, si le serveur n'est pas disponible, je ne veux pas de popup qui lui dise qu'il n'est pas connecté. Le but, c'est que les informations soient autant que possibles stockées en local pour tout ce qui est necessaire au bon affichage de l'application sans pour autant donner de mauvaises ou de fausses informations (par exemple, garder les exercices créés, les programmes, les séances etc en local, si plus tard on calcule des statistiques pareilles, les garder aussi en local, si il y a un systeme de compte, garder la photo de profile ainsi que le pseudo etc en local. En bref la référence reste encore une fois Heavy qui fait très bien ça). Ajoute ceci à la mémoire du projet pour les futurs features qui traiteront de ça.

View File

@ -1,6 +1,6 @@
---
issueRef: "#62"
version: 1
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedAt: 1784481549150
version: 2
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
updatedAt: 1784487426036
---

View File

@ -2,15 +2,15 @@
id: "a53d84b5-06d9-4683-ac64-9100cb60669f"
number: 62
title: "[QA] Validation exercices à étapes, persistance et historique"
status: "open"
status: "qa"
priority: "medium"
sprint: null
links: [{"target":"#54","kind":"relatesTo"},{"target":"#60","kind":"dependsOn"},{"target":"#61","kind":"dependsOn"}]
agentRefs: [{"agentId":"7efa512f-3b3a-47b5-ade0-a2dd13073055","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
createdAt: 1784481549150
updatedAt: 1784481549150
version: 1
updatedAt: 1784487426036
version: 2
---
Préparer et exécuter le plan QA pour les exercices à étapes : création/édition et limites max 8, snapshots programme/séance, exécution étapes temps/répétitions, bips 3/2/1/0, enchaînement de chronos, skips étape/passage/série, pause/reprise/kill app, projection historique, édition ponctuelle sans déplacer la progression ni mélanger résultats d'étape et résultats de série.

View File

@ -0,0 +1,6 @@
---
issueRef: "#64"
version: 1
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedAt: 1784488337677
---

View File

@ -0,0 +1,16 @@
---
id: "4a18ba38-9b18-4b39-99a4-ad5a8779e47f"
number: 64
title: "[DevBackend] Client online : session compte, stockage sécurisé et adapter API"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#63","kind":"relatesTo"}]
agentRefs: [{"agentId":"10ee045b-1c41-479e-ba03-dceed9edd495","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
createdAt: 1784488337677
updatedAt: 1784488337677
version: 1
---
Ajouter le socle client online côté domain/application/infrastructure : entité locale `UserAccountSession` (profil cache non sensible), ports `AuthTokenStore`, `OnlineAccountRepository`/`RemoteGameTimeApi`, adapter HTTP sous `lib/infrastructure/remote/` basé sur `package:http` avec timeouts courts et erreurs typées silencieuses. Stocker access/refresh token via `flutter_secure_storage`; stocker email/pseudo/avatar/statut sync en Drift. Ne jamais bloquer l'usage offline si l'API échoue.

View File

@ -0,0 +1,6 @@
---
issueRef: "#65"
version: 1
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedAt: 1784488343589
---

View File

@ -0,0 +1,16 @@
---
id: "f0c554b7-e388-49b3-aa74-0a47886961ad"
number: 65
title: "[DevBackend] Sync client incrémentale LWW vers API serveur"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#63","kind":"relatesTo"},{"target":"#64","kind":"dependsOn"}]
agentRefs: [{"agentId":"10ee045b-1c41-479e-ba03-dceed9edd495","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
createdAt: 1784488343589
updatedAt: 1784488343589
version: 1
---
Remplacer le `NoOpSyncGateway` par une orchestration réelle offline-first. Mapper Exercise, Program, WorkoutTemplate, WorkoutHistory et MediaAsset metadata vers `resourceType/clientId/schemaVersion/clientUpdatedAt/deletedAt/payload`. Utiliser `change_log`, `syncState`, `updatedAt` et `localRevision` pour pousser les mutations, stocker localement `serverCursor`, appliquer `/sync/pull` LWW sans résolution interactive, puis marquer les ressources acceptées comme synced. Les erreurs réseau restent silencieuses et déclenchent retry différé.

View File

@ -0,0 +1,6 @@
---
issueRef: "#66"
version: 1
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedAt: 1784488349264
---

View File

@ -0,0 +1,16 @@
---
id: "bdcf80ef-1360-4baa-9c49-86b091412ba1"
number: 66
title: "[DevBackend] Partage client : use cases, inbox cache et import local"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#63","kind":"relatesTo"},{"target":"#64","kind":"dependsOn"},{"target":"#65","kind":"dependsOn"}]
agentRefs: [{"agentId":"10ee045b-1c41-479e-ba03-dceed9edd495","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
createdAt: 1784488349264
updatedAt: 1784488349264
version: 1
---
Ajouter les ports/use cases client pour `POST /shares`, `GET /shares/inbox`, accept/decline/revoke. Stocker une inbox locale lisible offline et une file d'actions de partage en attente si réseau indisponible. À l'acceptation, importer une copie locale indépendante du Programme ou WorkoutTemplate depuis le payload reçu si disponible; l'accusé serveur peut partir ensuite, et la ressource créée côté serveur retombe aussi via le prochain `/sync/pull` sans doublon grâce aux IDs/mapping.

View File

@ -0,0 +1,6 @@
---
issueRef: "#67"
version: 1
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedAt: 1784488354627
---

View File

@ -0,0 +1,16 @@
---
id: "961d38c4-a124-47da-8118-be8b559fc617"
number: 67
title: "[DevFrontend] Profil et écrans auth optionnels"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#63","kind":"relatesTo"},{"target":"#64","kind":"dependsOn"}]
agentRefs: [{"agentId":"9933c93a-b8a1-4164-a3bb-7063fdad747d","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
createdAt: 1784488354627
updatedAt: 1784488354627
version: 1
---
Ajouter l'entrée `Profil` sur l'accueil et les surfaces UX connecté/déconnecté. Créer les écrans `Créer un compte`, `Se connecter`, confirmation logout. La connexion reste optionnelle, jamais affichée au démarrage. Erreurs serveur/réseau uniquement inline dans les formulaires, jamais popup globale. Profil affiché depuis cache local même hors ligne.

View File

@ -0,0 +1,6 @@
---
issueRef: "#68"
version: 1
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedAt: 1784488359218
---

View File

@ -0,0 +1,16 @@
---
id: "ac634023-e7ba-4588-9c7c-9f93c12d9aad"
number: 68
title: "[DevFrontend] Statut de synchronisation discret et action manuelle"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#63","kind":"relatesTo"},{"target":"#65","kind":"dependsOn"},{"target":"#67","kind":"dependsOn"}]
agentRefs: [{"agentId":"9933c93a-b8a1-4164-a3bb-7063fdad747d","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
createdAt: 1784488359218
updatedAt: 1784488359218
version: 1
---
Afficher la section Synchronisation dans Profil : en cours, à jour, jamais faite, retry automatique, hors ligne. Ajouter `Synchroniser maintenant`. Ne jamais afficher de snackbar/dialog d'échec réseau hors contexte Profil. Optionnel : sous-titre discret de l'entrée Profil sur l'accueil.

View File

@ -0,0 +1,6 @@
---
issueRef: "#69"
version: 1
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedAt: 1784488364646
---

View File

@ -0,0 +1,16 @@
---
id: "05482a20-83a6-44da-b0c6-d065a5a1ffba"
number: 69
title: "[DevFrontend] Partage sortant et boîte de réception"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#63","kind":"relatesTo"},{"target":"#66","kind":"dependsOn"},{"target":"#67","kind":"dependsOn"}]
agentRefs: [{"agentId":"9933c93a-b8a1-4164-a3bb-7063fdad747d","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
createdAt: 1784488364646
updatedAt: 1784488364646
version: 1
---
Ajouter l'action `Partager` dans les écrans programme/séance enregistrés, formulaire email destinataire, états déconnecté et messages discrets. Ajouter `Profil > Partages reçus`, liste inbox, accepter/refuser, import local des programmes/séances reçus. Les erreurs réseau restent inline/neutres; accepter un partage rend la copie disponible offline.

View File

@ -0,0 +1,6 @@
---
issueRef: "#70"
version: 1
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedAt: 1784488373778
---

View File

@ -0,0 +1,16 @@
---
id: "cb93ee24-0041-4926-b0c6-3ab26aab46ec"
number: 70
title: "[QA] Validation client online offline-first"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#63","kind":"relatesTo"},{"target":"#68","kind":"dependsOn"},{"target":"#69","kind":"dependsOn"}]
agentRefs: [{"agentId":"7efa512f-3b3a-47b5-ade0-a2dd13073055","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
updatedBy: {"kind":"agent","agent_id":"f8f40941-ecf7-4830-b9de-8818a099f448"}
createdAt: 1784488373778
updatedAt: 1784488373778
version: 1
---
Valider le chantier client online : app utilisable sans compte, login/register/logout optionnels, tokens persistés, profil cache hors ligne, sync push/pull LWW, erreurs réseau silencieuses, retry différé, partage sortant ciblé, inbox, accept/decline/revoke, import local offline, absence de régression sur les parcours locaux exercices/programmes/séances/historique.

View File

@ -1,3 +1,3 @@
{
"nextNumber": 64
"nextNumber": 71
}

View File

@ -525,13 +525,13 @@
"issueRef": "#46",
"path": "46",
"title": "Créer un serveur headless pour l'application",
"status": "open",
"status": "qa",
"priority": "low",
"sprint": "4237adfd-91eb-45ff-9f32-6ce1daa39822",
"assignedAgentIds": [
"57695b92-24d0-4876-837c-76116e70a6ae"
],
"updatedAt": 1784482343900
"updatedAt": 1784488112374
},
{
"issueRef": "#47",
@ -607,13 +607,13 @@
"issueRef": "#54",
"path": "54",
"title": "Exercice à plusieurs étapes",
"status": "open",
"status": "qa",
"priority": "medium",
"sprint": "1bb8bdf2-9c35-4f53-9a31-1390a47bec63",
"assignedAgentIds": [
"57695b92-24d0-4876-837c-76116e70a6ae"
],
"updatedAt": 1784451193831
"updatedAt": 1784487430850
},
{
"issueRef": "#56",
@ -631,13 +631,13 @@
"issueRef": "#57",
"path": "57",
"title": "Allimenter la mémoire projet pour l'UI online de l'app",
"status": "open",
"status": "closed",
"priority": "medium",
"sprint": "4237adfd-91eb-45ff-9f32-6ce1daa39822",
"assignedAgentIds": [
"57695b92-24d0-4876-837c-76116e70a6ae"
],
"updatedAt": 1784482343900
"updatedAt": 1784488107329
},
{
"issueRef": "#58",
@ -691,13 +691,13 @@
"issueRef": "#62",
"path": "62",
"title": "[QA] Validation exercices à étapes, persistance et historique",
"status": "open",
"status": "qa",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [
"7efa512f-3b3a-47b5-ade0-a2dd13073055"
],
"updatedAt": 1784481549150
"updatedAt": 1784487426036
},
{
"issueRef": "#63",
@ -710,6 +710,90 @@
"57695b92-24d0-4876-837c-76116e70a6ae"
],
"updatedAt": 1784482673684
},
{
"issueRef": "#64",
"path": "64",
"title": "[DevBackend] Client online : session compte, stockage sécurisé et adapter API",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [
"10ee045b-1c41-479e-ba03-dceed9edd495"
],
"updatedAt": 1784488337677
},
{
"issueRef": "#65",
"path": "65",
"title": "[DevBackend] Sync client incrémentale LWW vers API serveur",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [
"10ee045b-1c41-479e-ba03-dceed9edd495"
],
"updatedAt": 1784488343589
},
{
"issueRef": "#66",
"path": "66",
"title": "[DevBackend] Partage client : use cases, inbox cache et import local",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [
"10ee045b-1c41-479e-ba03-dceed9edd495"
],
"updatedAt": 1784488349264
},
{
"issueRef": "#67",
"path": "67",
"title": "[DevFrontend] Profil et écrans auth optionnels",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [
"9933c93a-b8a1-4164-a3bb-7063fdad747d"
],
"updatedAt": 1784488354627
},
{
"issueRef": "#68",
"path": "68",
"title": "[DevFrontend] Statut de synchronisation discret et action manuelle",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [
"9933c93a-b8a1-4164-a3bb-7063fdad747d"
],
"updatedAt": 1784488359218
},
{
"issueRef": "#69",
"path": "69",
"title": "[DevFrontend] Partage sortant et boîte de réception",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [
"9933c93a-b8a1-4164-a3bb-7063fdad747d"
],
"updatedAt": 1784488364646
},
{
"issueRef": "#70",
"path": "70",
"title": "[QA] Validation client online offline-first",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [
"7efa512f-3b3a-47b5-ade0-a2dd13073055"
],
"updatedAt": 1784488373778
}
]
}