From d4df3822b7fd26d5ab5f85b51df396ca04d8498b Mon Sep 17 00:00:00 2001 From: Blomios Date: Fri, 28 Aug 2026 23:11:16 +0200 Subject: [PATCH] =?UTF-8?q?docs(qa-261):=20ajoute=20documents=20conformit?= =?UTF-8?q?=C3=A9=20et=20scripts=20QA=20pour=20release=20Android?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ajoute privacy-policy-v1.md et release-compliance-checklist.md - Ajoute documents QA gates #238-#243 - Ajoute scripts de validation repo-only et device runbooks - Prépare checklists exécutables avant upload Play fermé Ticket #261 --- docs/legal/privacy-policy-v1.md | 91 +++ docs/qa-functional-test-plan-238.md | 629 +++++++++++++++++++++ docs/qa-gate-239-functional-flutter.md | 63 +++ docs/qa-gate-240-drift-core-offline.md | 57 ++ docs/qa-gate-241-critical-screens-smoke.md | 73 +++ docs/qa-gate-242-monetization-free-pro.md | 80 +++ docs/qa-gate-243-device-runbooks.md | 105 ++++ docs/release-compliance-checklist.md | 73 +++ tool/qa_device_health_connect.sh | 138 +++++ tool/qa_device_import_export_real.sh | 129 +++++ tool/qa_device_watch_companion.sh | 154 +++++ tool/qa_gate_241_critical_screens_smoke.sh | 17 + tool/qa_gate_242_monetization_partial.sh | 14 + 13 files changed, 1623 insertions(+) create mode 100644 docs/legal/privacy-policy-v1.md create mode 100644 docs/qa-functional-test-plan-238.md create mode 100644 docs/qa-gate-239-functional-flutter.md create mode 100644 docs/qa-gate-240-drift-core-offline.md create mode 100644 docs/qa-gate-241-critical-screens-smoke.md create mode 100644 docs/qa-gate-242-monetization-free-pro.md create mode 100644 docs/qa-gate-243-device-runbooks.md create mode 100644 docs/release-compliance-checklist.md create mode 100755 tool/qa_device_health_connect.sh create mode 100755 tool/qa_device_import_export_real.sh create mode 100755 tool/qa_device_watch_companion.sh create mode 100755 tool/qa_gate_241_critical_screens_smoke.sh create mode 100755 tool/qa_gate_242_monetization_partial.sh diff --git a/docs/legal/privacy-policy-v1.md b/docs/legal/privacy-policy-v1.md new file mode 100644 index 0000000..71800f3 --- /dev/null +++ b/docs/legal/privacy-policy-v1.md @@ -0,0 +1,91 @@ +# GameTime Privacy Policy + +Version: 1.0 +Effective date: 2026-08-22 +Status: repo reference draft for release preparation + +## Scope + +This policy covers the GameTime mobile app, including the Android phone app, +the optional Wear OS companion, account features, sharing, synchronization, +purchase entitlement checks, and optional Health Connect integration. + +## Data We Handle + +GameTime is designed as an offline-first workout tracker. Depending on the +features used, the app may handle: + +- workout library content created by the user, including exercises, programs, + workout templates, timers, scores, repetitions, session history, and local + media selected for exercises +- account identifiers such as email address and authentication tokens when the + user creates an account or signs in +- shared workout resources and recipient email addresses when the sharing + feature is used +- purchase entitlement status needed to determine whether the account is on the + Free or Pro plan +- optional workout telemetry such as heart rate, distance, calories, and + exercise records when the user explicitly enables Health Connect integration +- optional live workout state and commands exchanged with the Wear OS companion + +## Free and Pro Features + +Sharing remains free. The Free plan limits the editable workout library, not +basic workout execution. Imported or shared resources count toward the +receiving account's quota when accepted. Pro provides unlimited library capacity +and synchronization. + +The Wear OS companion and Health Connect integration are free features and are +not paywalled. + +## Local Storage and Offline Use + +Workout data is stored locally on the device first. The app is intended to keep +working without network access, including before any server synchronization has +been configured. + +## Synchronization and Sharing + +When synchronization is enabled, workout library and account data may be sent to +the GameTime server so the account can restore or synchronize data. When sharing +is used, the selected resources and recipient identifiers are sent to the server +so recipients can receive, accept, decline, or revoke shares. + +## Health Connect + +Health Connect access is optional. GameTime requests only the health permissions +needed for the enabled workout features. Health data is used to support workout +tracking and export flows shown in the app. The user can revoke Health Connect +permissions from Android settings. + +## Wear OS Companion + +The Wear OS companion exchanges live session state, commands, and available +metrics with the phone app. The companion is optional and depends on the Android +Wear Data Layer between paired devices. + +## Purchases and Entitlements + +Purchase and entitlement data is used to unlock Pro functionality such as +unlimited library capacity and synchronization. GameTime does not use purchase +state to restrict sharing, the Wear OS companion, Health Connect, or basic +workout execution. + +## Data Retention and Deletion + +Local workout data remains on the device until the user deletes it or removes +the app. Server-side account, synchronization, sharing, and entitlement data +requires an operational account management process before public release. + +## Security + +Release Android builds must use HTTPS for remote GameTime server traffic. +Cleartext HTTP is permitted only for local debug/profile development builds. +Authentication tokens are treated as sensitive credentials and should be stored +through the platform secure storage adapter. + +## Contact + +Before public distribution, replace this section with the legal support contact +and the public URL that will be submitted to the Play Console. + diff --git a/docs/qa-functional-test-plan-238.md b/docs/qa-functional-test-plan-238.md new file mode 100644 index 0000000..c4e356e --- /dev/null +++ b/docs/qa-functional-test-plan-238.md @@ -0,0 +1,629 @@ +# Ticket #238 — Cadrage QA runnable des features principales + +## Objectif + +Ce document sert de base opérationnelle au nouveau process TDD GameTime. +Il fixe : + +- l'ordre recommandé de couverture des features majeures +- les suites attendues par niveau de test +- la stratégie d'implémentation runnable +- les commandes cibles à exécuter +- le backlog initial d'automatisation prioritaire + +Le principe directeur est simple : verrouiller d'abord les parcours qui portent la valeur produit et les régressions les plus coûteuses, avant d'étendre la couverture device et infra. + +## Preuves réelles ajoutées le 22 août 2026 + +Preuves exécutées sur `/tmp/gametime-src-1787384228` : + +- gate `#239` verte +- gate `#240` verte +- smoke `#241` vert +- gate `#242` verte +- `dart test` serveur vert + +Conséquence : + +- le socle QA Flutter transverse est désormais prouvé exécutable +- le coeur offline Drift est prouvé exécutable +- la gate monétisation actuellement cadrée est prouvée exécutable +- la validation device reste distincte et passe par `#243` + +## Constat repo au 21 août 2026 + +Le dépôt contient déjà une base exploitable : + +- tests Flutter domaine/application/infrastructure dans `test/application`, `test/infrastructure`, `test/domain_import_boundaries_test.dart` +- nombreux tests widget écran par écran dans `test/presentation` +- premier harnais fonctionnel mémoire dans `test/support/functional_harness.dart` +- première suite fonctionnelle transverse dans `test/functional/functional_coverage_test.dart` +- suite montre dédiée dans `watch_app/test/presentation` +- suite serveur Dart dans `server/test` +- checklist d'intégration réelle infra dans `server/docs/integration-checklist.md` + +Ce qui manque pour relancer le delivery vers la prod n'est pas une base de tests, mais une hiérarchie claire : + +- quels parcours servent de gate de non-régression +- quels niveaux de tests portent chaque feature +- quelles suites doivent tourner en local, en CI rapide, en CI complète et en validation manuelle scriptée + +## Convention d'exécution runnable + +Dans l'environnement actuel, les commandes Flutter et Dart passent en forçant un `HOME` writable et en coupant l'analytics. + +Convention à utiliser pour les runners locaux et CI : + +```bash +export HOME=/tmp +export XDG_CONFIG_HOME=/tmp +export FLUTTER_SUPPRESS_ANALYTICS=true +export DART_SUPPRESS_ANALYTICS=true +``` + +Preuve minimale vérifiée dans ce ticket : + +- `flutter test test/functional/functional_coverage_test.dart --plain-name 'builders create readable exercise, program and template scenarios'` +- `dart test test/health_test.dart` depuis `server/` + +Ces deux commandes passent avec la convention ci-dessus. + +## Ordre de couverture recommandé + +### Lot 1 — Gate prod minimale téléphone offline-first + +But : garantir que l'app principale remplit sa promesse cœur sans compte ni sync. + +Features incluses : + +- bibliothèque d'exercices +- composition de programmes +- composition de séances +- exécution d'une séance +- enregistrement d'historique +- reprise d'une séance en cours +- progression issue de l'historique + +Pourquoi en premier : + +- c'est le cœur de la valeur GameTime +- la plupart des invariants sont déjà testables en mémoire +- ce lot permet de relancer le développement produit sans attendre l'infra distante + +### Lot 2 — Variantes métier à fort risque de régression + +Features incluses : + +- score manuel +- score chrono +- timers de série et de repos +- séquences d'étapes +- correction d'une série passée +- import/export local + +Pourquoi ensuite : + +- ces variantes cassent facilement les écrans et les use cases +- elles demandent des suites de comportement plus transverses que du simple widget isolé + +### Lot 3 — Compte, sync et partage + +Features incluses : + +- profil connecté/déconnecté +- auth +- sync +- boîte de réception des partages +- partage de programme et de séance +- import de partage accepté + +Pourquoi après le lot 1 : + +- forte dépendance à l'API et à des fixtures serveur +- besoin de distinguer clairement tests clients mockés, tests serveur réels et smoke end-to-end + +### Lot 4 — Intégrations gratuites device + +Features incluses : + +- Health Connect +- compagnon montre Android/Wear +- projection de séance vers la montre +- télémétrie live montre + +Pourquoi en quatrième : + +- important produit, mais plus coûteux à rendre deterministic +- nécessite émulateurs / devices / bridge natif + +### Lot 5 — Validation déploiement et packaging + +Features incluses : + +- build Android +- build watch +- bootstrap serveur Docker/PostgreSQL +- smoke API réelle + +Pourquoi en dernier : + +- ce lot doit s'appuyer sur des fondations fonctionnelles déjà stables + +## Matrice feature -> suites attendues + +### 1. Exercices + +Parcours nominaux : + +- créer un exercice simple +- créer un exercice avec reps, temps et score +- ajouter tags et médias +- définir une icône média +- configurer des étapes +- modifier puis supprimer un exercice + +Cas limites : + +- aucune mesure active +- neuvième étape refusée +- sixième image refusée +- étape invalide +- exercice seedé modifié + +Suites attendues : + +- unitaires : validations métier et normalisation +- intégration : persistance Drift des exercices, tags, médias, étapes +- widget : formulaire réel et liste filtrable +- end-to-end/manuel scripté : ajout complet avec média réel sur device + +Base existante : + +- `test/presentation/exercise_library_screen_test.dart` +- `test/infrastructure/drift_repositories_test.dart` + +### 2. Programmes + +Parcours nominaux : + +- créer un programme depuis des exercices existants +- configurer séries, cibles, repos +- dupliquer +- filtrer +- partager + +Cas limites : + +- programme sans exercice +- exercice snapshot incomplet +- partage sans compte + +Suites attendues : + +- unitaires : construction snapshot et validations de configuration +- intégration : lecture/écriture repository +- widget : formulaire, liste, duplication, partage +- end-to-end/manuel scripté : création puis partage depuis un compte réel + +Base existante : + +- `test/presentation/program_screen_test.dart` + +### 3. Séances / templates + +Parcours nominaux : + +- créer une séance avec un ou plusieurs programmes +- configurer overrides +- dupliquer +- lancer depuis la liste + +Cas limites : + +- séance sans programme +- aucune exécution possible +- legacy invalide non bloquante + +Suites attendues : + +- unitaires : résolution des snapshots et overrides +- intégration : persistance template + programme snapshot +- widget : création/édition/lancement +- end-to-end/manuel scripté : création complète puis lancement + +Base existante : + +- `test/presentation/workout_template_screen_test.dart` +- `test/functional/functional_coverage_test.dart` + +### 4. Exécution de séance + +Parcours nominaux : + +- démarrer depuis une séance +- exécuter score manuel +- exécuter chrono score +- gérer repos +- pause/reprise +- terminer une série +- quitter et reprendre +- compléter la séance +- enregistrer l'historique +- relancer depuis l'historique + +Cas limites : + +- séance invalide +- repos resynchronisé +- chrono jamais démarré +- dernière série sans repos +- série passée corrigée +- skip de série +- skip de séquence + +Suites attendues : + +- unitaires : transitions d'état de session, repos, chrono, score, steps +- intégration : persistance session active -> historique +- widget : écran d'exécution, plan, édition de série passée, reprise +- end-to-end/manuel scripté : parcours complet réel sur téléphone + +Base existante : + +- `test/application/use_cases_test.dart` +- `test/application/session_notification_use_cases_test.dart` +- `test/presentation/workout_execution_screen_test.dart` +- `test/functional/functional_coverage_test.dart` + +### 5. Historique et progression + +Parcours nominaux : + +- consulter les séances passées +- ouvrir le détail +- supprimer +- relancer +- visualiser la progression globale +- visualiser la progression par exercice + +Cas limites : + +- historique vide +- historique legacy invalide +- score chrono affiché comme temps +- ouverture de détail depuis point de graphe + +Suites attendues : + +- unitaires : agrégations progression et mapping métriques +- intégration : repository historique +- widget : écrans Historique et Progression +- end-to-end/manuel scripté : séance jouée puis visible dans progression + +Base existante : + +- `test/presentation/history_screen_test.dart` +- `test/presentation/progression_screen_test.dart` + +### 6. Compte, auth, sync et partage + +Parcours nominaux : + +- créer un compte +- se connecter +- se déconnecter +- synchroniser +- partager un programme +- partager une séance +- recevoir un partage +- accepter et importer +- décliner + +Cas limites : + +- erreur login inline +- erreur serveur dédiée +- token invalide +- conflit LWW sync +- partage déjà répondu +- email inconnu +- quota receveur plein + +Suites attendues : + +- unitaires : use cases auth/sync/share, règles quota/import +- intégration : client HTTP, API serveur, repositories serveur +- widget : Profil, Inbox, formulaires de partage +- end-to-end/manuel scripté : 2 comptes réels, partage puis sync + +Base existante : + +- client Flutter : `test/presentation/profile_screen_test.dart`, `test/presentation/share_inbox_screen_test.dart`, `test/infrastructure/remote/*.dart` +- serveur Dart : `server/test/auth_*`, `server/test/sync_*`, `server/test/share_*` + +Note monétisation : + +- le partage reste gratuit +- le quota free limite la bibliothèque éditable, pas l'exécution +- les objets importés/partagés comptent côté receveur à l'acceptation +- le backlog QA devra explicitement ajouter les cas quota multi-comptes et restauration + +### 7. Import / export local + +Parcours nominaux : + +- exporter ses données +- importer en fusion +- importer en remplacement total + +Cas limites : + +- fichier invalide +- annulation silencieuse +- séance active qui bloque l'import +- double confirmation destructive + +Suites attendues : + +- unitaires : parsing et règles de fusion/remplacement +- intégration : repositories et frontières d'import +- widget : flux import/export depuis Profil +- end-to-end/manuel scripté : vrai fichier sur device + +Base existante : + +- `test/presentation/profile_screen_test.dart` +- `test/domain_import_boundaries_test.dart` + +### 8. Health Connect + +Parcours nominaux : + +- afficher l'état d'intégration +- demander les permissions +- rafraîchir le statut + +Cas limites : + +- permissions partielles +- refus explicite +- fallback vers réglages +- accès bloqué sans action +- échec d'appel natif + +Suites attendues : + +- unitaires : mapping des statuts natifs +- intégration : gateway Health Connect mockée +- widget : écran Paramètres / Intégrations +- manuel scripté : device Android compatible Health Connect + +Base existante : + +- `test/application/health_connect_use_cases_test.dart` +- `test/presentation/settings_screen_test.dart` + +### 9. Watch companion + +Parcours nominaux : + +- projeter une séance active vers la montre +- piloter score / timer / pause depuis la montre +- remonter la fréquence cardiaque et la télémétrie +- gérer reconnexion et fraîcheur de projection + +Cas limites : + +- téléphone absent +- projection stale +- actions bloquées en reconnexion +- timer visible en pause +- TTL dépassé + +Suites attendues : + +- unitaires : contrat de projection, commandes, policy de retry +- intégration : bridge natif téléphone <-> montre +- widget : UI montre +- manuel scripté : téléphone Android + émulateur/device Wear + +Base existante : + +- `test/application/watch_companion_projection_test.dart` +- `test/application/watch_companion_command_handler_test.dart` +- `test/infrastructure/watch_bridge/wear_data_layer_adapter_test.dart` +- `watch_app/test/presentation/watch_session_screen_test.dart` +- `watch_app/android/app/src/test/kotlin/com/gametime/watch/bridge/WatchExerciseMetricsRetryPolicyTest.kt` + +## Stratégie runnable par niveau de suite + +### 1. Suites rapides obligatoires sur chaque lot + +Objectif : feedback en quelques minutes, sans device réel. + +Contenu : + +- unitaires domaine/application +- intégration repository mémoire ou Drift locale +- widget ciblés +- fonctionnels mémoire via `FunctionalTestHarness` + +Règle : + +- toute nouvelle feature/correction doit d'abord produire ou enrichir une suite de ce niveau + +### 2. Suites de référence transverses + +Objectif : prouver que les briques s'assemblent sur des parcours principaux. + +Contenu : + +- un petit nombre de scénarios fonctionnels end-to-end en mémoire côté Flutter +- un petit nombre de scénarios API serveur de bout en bout en local + +Règle : + +- garder ces scénarios courts, lisibles et déterministes +- ne pas y mettre toutes les permutations écran par écran + +### 3. Suites device / infra scriptées + +Objectif : couvrir les frontières impossibles à prouver en sandbox mémoire. + +Contenu : + +- import/export réel +- Health Connect réel +- compagnon montre réel +- Docker/PostgreSQL/smoke API réel + +Règle : + +- documenter chaque parcours sous forme de script de validation réexécutable +- promouvoir en automatisation seulement après stabilisation du protocole et des fixtures + +## Commandes cibles + +### Flutter app + +Installer les dépendances : + +```bash +export HOME=/tmp +export XDG_CONFIG_HOME=/tmp +export FLUTTER_SUPPRESS_ANALYTICS=true +export DART_SUPPRESS_ANALYTICS=true +./.ideai/flutter-sdk-1785572580/bin/flutter pub get +``` + +Smoke domaine/widget/functional : + +```bash +./.ideai/flutter-sdk-1785572580/bin/flutter test +./.ideai/flutter-sdk-1785572580/bin/flutter test test/functional/functional_coverage_test.dart +./.ideai/flutter-sdk-1785572580/bin/flutter test test/presentation/workout_execution_screen_test.dart +./.ideai/flutter-sdk-1785572580/bin/flutter test test/presentation/profile_screen_test.dart +``` + +### Watch app + +```bash +cd watch_app +export HOME=/tmp +export XDG_CONFIG_HOME=/tmp +export FLUTTER_SUPPRESS_ANALYTICS=true +export DART_SUPPRESS_ANALYTICS=true +../.ideai/flutter-sdk-1785572580/bin/flutter pub get +../.ideai/flutter-sdk-1785572580/bin/flutter test +``` + +### Serveur + +```bash +cd server +export HOME=/tmp +export XDG_CONFIG_HOME=/tmp +export DART_SUPPRESS_ANALYTICS=true +/home/anthony/Documents/Projects/GameTime/.ideai/flutter-sdk-1785572580/bin/dart pub get +/home/anthony/Documents/Projects/GameTime/.ideai/flutter-sdk-1785572580/bin/dart test +``` + +### Intégration PostgreSQL réelle + +```bash +cd server +TEST_DATABASE_URL=postgres://gametime:gametime@localhost:5432/gametime \ +/home/anthony/Documents/Projects/GameTime/.ideai/flutter-sdk-1785572580/bin/dart test +``` + +### Build / smoke Android manuel scripté + +```bash +export HOME=/tmp +export XDG_CONFIG_HOME=/tmp +export FLUTTER_SUPPRESS_ANALYTICS=true +export DART_SUPPRESS_ANALYTICS=true +./.ideai/flutter-sdk-1785572580/bin/flutter build apk --debug +./.ideai/flutter-sdk-1785572580/bin/flutter run +``` + +## Backlog initial d'automatisation + +### Priorité P0 — à garder verte en permanence + +- stabiliser `test/functional/functional_coverage_test.dart` comme gate Flutter transverse +- y conserver au moins 4 scénarios de référence : + - création exercice/programme/séance via formulaires réels + - exécution complète avec score manuel + chrono + repos + historique + replay + - reprise de séance sauvegardée + - séquences d'étapes avec skip et correction de résultat +- définir une commande CI rapide `flutter test test/functional/functional_coverage_test.dart` +- définir une commande CI serveur `dart test` dans `server/` + +### Priorité P1 — verrouiller le cœur prod offline + +- compléter une suite intégration Drift dédiée au cycle exercice -> programme -> template -> session -> historique +- ajouter une suite application dédiée aux invariants de progression à partir d'historiques réels +- ajouter une suite widget de navigation nominale accueil -> séance -> historique -> progression +- isoler un groupe "smoke critical screens" pour `home`, `exercise_library`, `program`, `workout_template`, `workout_execution`, `history`, `progression` + +### Priorité P2 — verrouiller les frontières produit payantes et multi-comptes + +- ajouter tests use case et serveur pour quota free/pro +- couvrir import de partage quand quota receveur est plein +- couvrir multi-comptes, restauration et sync Pro +- couvrir offline puis resync après reconnexion + +### Priorité P3 — transformer les checklists device en scripts réexécutables + +- écrire un script manuel standardisé Health Connect +- écrire un script manuel standardisé watch companion +- écrire un script manuel standardisé partage entre deux comptes réels +- écrire un script manuel standardisé import/export fichier réel + +## Première découpe TDD recommandée pour relancer le delivery + +### Sprint QA-A — gate rapide commune + +- figer la convention d'environnement de test +- garder vert : + - `test/functional/functional_coverage_test.dart` + - `server/test` + - `watch_app/test` + +### Sprint QA-B — cœur offline téléphone + +- enrichir le functional harness pour couvrir navigation nominale complète +- compléter les invariants manquants exercice -> programme -> template -> exécution -> historique -> progression + +### Sprint QA-C — compte/sync/partage + +- préparer fixtures API et scénarios 2 comptes +- séparer clairement : + - tests client mockés + - tests serveur réels + - smoke manuels API + client + +### Sprint QA-D — device integrations + +- formaliser scripts de validation montre et Health Connect +- décider ensuite ce qui mérite une automatisation instrumentée + +## Critères de sortie pour qu'une feature soit "finie" + +Une feature n'est pas considérée terminée tant que : + +- le plan fonctionnel du lot existe +- les tests unitaires / intégration / widget prévus pour le lot existent +- les commandes de suites rapides ont réellement tourné +- les éventuels scripts manuels device/infra ont réellement été exécutés si la feature touche ces frontières +- les régressions critiques correspondantes sont absorbées dans les suites P0/P1 + +## Recommandation immédiate + +Pour redémarrer vers la prod sans disperser l'équipe : + +1. utiliser `test/functional/functional_coverage_test.dart` comme colonne vertébrale Flutter +2. considérer `server/test` comme gate du scope compte/sync/partage +3. ne pas lancer de nouvelle feature transverse sans ajouter son scénario dans le harnais fonctionnel ou dans une suite serveur équivalente +4. traiter Health Connect et watch companion comme checklists scriptées tant que le setup device n'est pas stabilisé en CI diff --git a/docs/qa-gate-239-functional-flutter.md b/docs/qa-gate-239-functional-flutter.md new file mode 100644 index 0000000..b28ea4e --- /dev/null +++ b/docs/qa-gate-239-functional-flutter.md @@ -0,0 +1,63 @@ +# QA Gate #239 — Suite fonctionnelle Flutter transverse + +## But + +Cette gate sert de socle rapide de non-régression Flutter pour la reprise TDD. +Elle couvre le parcours transverse minimal suivant : + +- création via formulaires réels +- exécution complète d'une séance +- reprise de séance +- séquences, skip et correction + +## Fichier source + +- `test/functional/functional_coverage_test.dart` + +## Pré-requis + +Utiliser un environnement writable pour Flutter : + +```bash +export HOME=/tmp +export XDG_CONFIG_HOME=/tmp +export FLUTTER_SUPPRESS_ANALYTICS=true +export DART_SUPPRESS_ANALYTICS=true +``` + +## Commande gate complète + +```bash +./.ideai/flutter-sdk-1785572580/bin/flutter test test/functional/functional_coverage_test.dart +``` + +## Commandes ciblées utiles + +Scénario de référence transverse : + +```bash +./.ideai/flutter-sdk-1785572580/bin/flutter test test/functional/functional_coverage_test.dart --plain-name "complete execution covers manual score, stopwatch, rests, skips, history and replay" +``` + +Scénario reprise : + +```bash +./.ideai/flutter-sdk-1785572580/bin/flutter test test/functional/functional_coverage_test.dart --plain-name "saved exit sessions resume from the execution UI without showing completion" +``` + +## Verdict attendu + +- vert si la base Flutter transverse est prête pour une boucle TDD rapide +- rouge si un parcours nominal majeur est cassé + +## Preuve réelle du 22 août 2026 + +Exécution rapportée verte sur `/tmp/gametime-src-1787384228`. + +Cette gate devient la référence rapide de non-régression Flutter transverse. + +## Usage dans la boucle TDD + +- avant implémentation d'une feature transverse touchant exécution/navigation +- après chaque lot modifiant les formulaires, l'exécution, l'historique ou la reprise +- comme gate rapide avant d'élargir vers les suites widget plus détaillées diff --git a/docs/qa-gate-240-drift-core-offline.md b/docs/qa-gate-240-drift-core-offline.md new file mode 100644 index 0000000..4e0d6a4 --- /dev/null +++ b/docs/qa-gate-240-drift-core-offline.md @@ -0,0 +1,57 @@ +# QA Gate #240 — Suite coeur offline Drift + +## But + +Cette gate sécurise le coeur offline local avant reprise intensive du développement. +Le point d'entrée recommandé est le parcours intégré : + +- exercice +- programme +- séance-template +- session active +- clôture en historique +- progression minimale + +## Fichier source + +- `test/infrastructure/drift_repositories_test.dart` + +## Pré-requis + +Utiliser le runner Flutter/Dart avec un environnement writable : + +```bash +export HOME=/tmp +export XDG_CONFIG_HOME=/tmp +export FLUTTER_SUPPRESS_ANALYTICS=true +export DART_SUPPRESS_ANALYTICS=true +``` + +## Commande gate complète + +```bash +./.ideai/flutter-sdk-1785572580/bin/flutter test test/infrastructure/drift_repositories_test.dart +``` + +## Point d'entrée coeur offline recommandé + +```bash +./.ideai/flutter-sdk-1785572580/bin/flutter test test/infrastructure/drift_repositories_test.dart --plain-name "QA core offline journey persists exercise to progression through local repositories" +``` + +## Verdict attendu + +- vert si la chaîne locale principale reste cohérente de la création jusqu'à la progression +- rouge si le domaine local ou la persistance Drift régressent sur le flux principal + +## Preuve réelle du 22 août 2026 + +Exécution rapportée verte sur `/tmp/gametime-src-1787384228`. + +Cette gate devient la référence coeur offline avant toute validation device ou release. + +## Usage dans la boucle TDD + +- à lancer avant et après chaque lot touchant les use cases offline +- à utiliser comme première preuve exécutable avant les suites écran par écran +- à compléter ensuite par les tests fonctionnels Flutter et, plus tard, les validations device diff --git a/docs/qa-gate-241-critical-screens-smoke.md b/docs/qa-gate-241-critical-screens-smoke.md new file mode 100644 index 0000000..c345f26 --- /dev/null +++ b/docs/qa-gate-241-critical-screens-smoke.md @@ -0,0 +1,73 @@ +# QA Gate #241 — Smoke écrans critiques Flutter + +## But + +Cette gate sert de détection rapide des régressions visibles majeures pendant la boucle TDD Flutter. + +Écrans couverts : + +- `home` +- `exercise library` +- `program` +- `workout template` +- `workout execution` +- `history` +- `progression` +- `profile` + +## Fichiers sources + +- `test/presentation/home_screen_test.dart` +- `test/presentation/exercise_library_screen_test.dart` +- `test/presentation/program_screen_test.dart` +- `test/presentation/workout_template_screen_test.dart` +- `test/presentation/workout_execution_screen_test.dart` +- `test/presentation/history_screen_test.dart` +- `test/presentation/progression_screen_test.dart` +- `test/presentation/profile_screen_test.dart` + +## Pré-requis + +```bash +export HOME=/tmp +export XDG_CONFIG_HOME=/tmp +export FLUTTER_SUPPRESS_ANALYTICS=true +export DART_SUPPRESS_ANALYTICS=true +``` + +## Point d'entrée recommandé + +```bash +./tool/qa_gate_241_critical_screens_smoke.sh +``` + +## Commande directe équivalente + +```bash +./.ideai/flutter-sdk-1785572580/bin/flutter test \ + test/presentation/home_screen_test.dart \ + test/presentation/exercise_library_screen_test.dart \ + test/presentation/program_screen_test.dart \ + test/presentation/workout_template_screen_test.dart \ + test/presentation/workout_execution_screen_test.dart \ + test/presentation/history_screen_test.dart \ + test/presentation/progression_screen_test.dart \ + test/presentation/profile_screen_test.dart +``` + +## Verdict attendu + +- vert si les écrans critiques restent fonctionnels sur les parcours nominaux majeurs +- rouge si une régression UI majeure casse la boucle TDD Flutter + +## Preuve réelle du 22 août 2026 + +Exécution rapportée verte sur `/tmp/gametime-src-1787384228`. + +Le script `./tool/qa_gate_241_critical_screens_smoke.sh` devient l'entrée de référence pour ce smoke. + +## Usage + +- avant merge d'un lot Flutter transverse +- après toute modification navigation/formulaires/exécution/historique/profil +- en complément de la gate `#239` diff --git a/docs/qa-gate-242-monetization-free-pro.md b/docs/qa-gate-242-monetization-free-pro.md new file mode 100644 index 0000000..f7efd3a --- /dev/null +++ b/docs/qa-gate-242-monetization-free-pro.md @@ -0,0 +1,80 @@ +# QA Gate #242 — Monétisation Free/Pro et partage/quota + +## But + +Matérialiser une première gate runnable autour de ce qui est déjà testable aujourd'hui, tout en isolant les blockers réels pour les règles Free/Pro non encore implémentées. + +## Ce qui est runnable maintenant + +Couverture partielle déjà testable : + +- profil et synchronisation côté Flutter +- partage / inbox / acceptation locale +- Health Connect gratuit +- companion montre gratuit + +Fichiers déjà exploitables : + +- `test/presentation/profile_screen_test.dart` +- `test/presentation/share_inbox_screen_test.dart` +- `test/presentation/settings_screen_test.dart` +- `test/application/health_connect_use_cases_test.dart` +- `test/application/watch_companion_projection_test.dart` + +## Point d'entrée recommandé + +```bash +./tool/qa_gate_242_monetization_partial.sh +``` + +## Pré-requis + +```bash +export HOME=/tmp +export XDG_CONFIG_HOME=/tmp +export FLUTTER_SUPPRESS_ANALYTICS=true +export DART_SUPPRESS_ANALYTICS=true +``` + +## Commande directe équivalente + +```bash +./.ideai/flutter-sdk-1785572580/bin/flutter test \ + test/presentation/profile_screen_test.dart \ + test/presentation/share_inbox_screen_test.dart \ + test/presentation/settings_screen_test.dart \ + test/application/health_connect_use_cases_test.dart \ + test/application/watch_companion_projection_test.dart +``` + +## Blockers réels + +Les contrats suivants ne sont pas encore testables proprement contre du code produit, car la surface métier n'existe pas encore clairement dans le repo : + +- quota `Free/Pro` +- refus création/édition quand quota plein +- import de partage chez receveur plein +- restauration d'achat +- statut `Pro` +- sync `Pro` +- multi-comptes monétisation + +## Recommandation de suite + +Avant d'écrire une vraie suite verte sur ces règles, il faut introduire un contrat métier testable, par exemple : + +- une policy `LibraryEntitlementPolicy` +- un use case `QuotaGuard` +- un état de compte distinguant `Free` et `Pro` +- une règle explicite d'acceptation de partage sous quota + +## Verdict attendu + +- vert aujourd'hui sur la gate partielle gratuite / partage +- rouge ou non applicable sur Free/Pro tant que la couche métier quota/billing n'existe pas + +## Preuve réelle du 22 août 2026 + +Exécution rapportée verte sur `/tmp/gametime-src-1787384228`. + +Cette gate valide la surface monétisation actuellement testable en local, sans fermer la QA release Android Play Store. diff --git a/docs/qa-gate-243-device-runbooks.md b/docs/qa-gate-243-device-runbooks.md new file mode 100644 index 0000000..51d1390 --- /dev/null +++ b/docs/qa-gate-243-device-runbooks.md @@ -0,0 +1,105 @@ +# QA Gate #243 — Runbooks manuels device + +## But + +Standardiser les validations device non encore raisonnablement automatisables, avec des scripts réexécutables de collecte d'artefacts et un déroulé manuel stable. + +Périmètre couvert : + +- Health Connect téléphone Android +- watch companion téléphone + Wear +- import/export réel sur téléphone + +## Références officielles + +### Health Connect + +Préparer la collecte : + +```bash +./tool/qa_device_health_connect.sh start +``` + +Finaliser la collecte : + +```bash +./tool/qa_device_health_connect.sh stop +``` + +### Watch companion + +Préparer la collecte : + +```bash +WATCH_SERIAL= ./tool/qa_device_watch_companion.sh start +``` + +Finaliser la collecte : + +```bash +WATCH_SERIAL= ./tool/qa_device_watch_companion.sh stop +``` + +### Import / export réel + +Préparer la collecte : + +```bash +./tool/qa_device_import_export_real.sh start +``` + +Finaliser la collecte : + +```bash +./tool/qa_device_import_export_real.sh stop +``` + +## Pré-requis communs + +- `adb` disponible dans le `PATH` +- appareil téléphone connecté et autorisé +- pour la montre : `WATCH_SERIAL` renseigné et montre visible via `adb devices -l` +- build GameTime fraîche installée sur le ou les appareils sous test + +## Artefacts attendus + +Chaque script crée un dossier sous : + +```bash +.ideai/artifacts/qa-device/ +``` + +Le dossier produit doit contenir au minimum : + +- `adb-devices.txt` +- fingerprint build device +- `logcat.txt` téléphone et/ou montre +- `steps.md` avec le scénario manuel joué +- `package-dumpsys-before.txt` et `package-dumpsys-after.txt` quand applicable + +## Verdict attendu par runbook + +### Health Connect + +- ouverture propre du flux permission ou fallback réglages +- retour propre dans GameTime +- état UI cohérent avant/après +- export fin de séance vérifiable si exercé + +### Watch companion + +- projection de séance visible sur montre +- actions montre répercutées sur téléphone +- métriques montre lisibles, dont les pas si disponibles +- clôture de séance cohérente côté téléphone et montre + +### Import / export réel + +- export de fichier réussi +- réimport `merge` cohérent +- réimport `replaceAll` cohérent sur dataset jetable +- refus attendu si une séance active bloque l'import + +## Limite actuelle au 22 août 2026 + +Ces runbooks rendent `#243` matérialisable et rejouable, mais la clôture QA device reste dépendante de la disponibilité réelle d'un appareil `adb`. diff --git a/docs/release-compliance-checklist.md b/docs/release-compliance-checklist.md new file mode 100644 index 0000000..cb9221d --- /dev/null +++ b/docs/release-compliance-checklist.md @@ -0,0 +1,73 @@ +# GameTime Release and Compliance Checklist + +This checklist tracks the repo-owned release/compliance work that can be closed +without Play Console access or physical devices. + +## Privacy Policy + +- Canonical repo draft: `docs/legal/privacy-policy-v1.md` +- Version: `1.0` +- Effective date: `2026-08-22` +- Before Play submission, publish the exact approved policy at a stable HTTPS + URL and enter that URL in Play Console. +- Keep future policy changes versioned in `docs/legal/`. + +## Product Entitlements + +The release surface must preserve these product invariants: + +- sharing is free +- Free limits the editable workout library, not basic workout execution +- imported/shared resources count against the receiver quota on acceptance +- Pro means unlimited library plus sync +- Wear OS companion is free +- Health Connect is free + +## Android Network Policy + +Phone app release builds: + +- keep `android.permission.INTERNET` in `android/app/src/main/AndroidManifest.xml` +- do not enable `android:usesCleartextTraffic` in the main manifest +- use HTTPS for `GAMETIME_API_BASE_URL` in release builds + +Phone app debug/profile builds: + +- may keep cleartext enabled through the debug/profile manifest overlays +- may use LAN HTTP URLs for local API development + +Wear OS companion: + +- keep release cleartext disabled +- keep companion functionality free and independent from Pro entitlement + +## Repo-Only Validation + +Run these checks before handing off to Play/device validation: + +```bash +rg -n 'usesCleartextTraffic="true"' android/app/src/main watch_app/android/app/src/main +rg -n 'usesCleartextTraffic="true"' android/app/src/debug android/app/src/profile +rg -n 'android.permission.INTERNET' android/app/src/main/AndroidManifest.xml +rg -n 'Health Connect|Wear OS|sharing is free|Pro means unlimited' docs/legal docs +``` + +Expected result: + +- no `usesCleartextTraffic="true"` in release/main manifests +- debug/profile overlays explicitly allow local cleartext +- phone release manifest still declares `INTERNET` +- privacy and release docs preserve the Free/Pro invariants + +## External Blockers + +These items cannot be closed from the repository alone: + +- Play Console app content forms +- public privacy-policy hosting URL +- production support/contact address approval +- Play Health Connect declaration/review, if required by the final release track +- validation on a real Android phone +- validation on a real Wear OS device +- production HTTPS endpoint and certificate verification + diff --git a/tool/qa_device_health_connect.sh b/tool/qa_device_health_connect.sh new file mode 100755 index 0000000..a001aa3 --- /dev/null +++ b/tool/qa_device_health_connect.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_ROOT="/home/anthony/Documents/Projects/GameTime" +ARTIFACT_BASE="${ARTIFACT_BASE:-$PROJECT_ROOT/.ideai/artifacts/qa-device}" +PHONE_SERIAL="${PHONE_SERIAL:-}" +PACKAGE_NAME="${PACKAGE_NAME:-com.idea.gametime}" + +usage() { + cat <<'EOF' +Usage: + ./tool/qa_device_health_connect.sh start + ./tool/qa_device_health_connect.sh stop + +Environment: + PHONE_SERIAL Optional adb serial for the phone under test + ARTIFACT_BASE Optional artifact root + PACKAGE_NAME Optional Android package name (default: com.idea.gametime) +EOF +} + +adb_cmd() { + if [[ -n "$PHONE_SERIAL" ]]; then + adb -s "$PHONE_SERIAL" "$@" + else + adb "$@" + fi +} + +require_adb() { + command -v adb >/dev/null 2>&1 || { + echo "adb not found in PATH." >&2 + exit 1 + } + adb start-server >/dev/null + adb_cmd get-state >/dev/null 2>&1 || { + echo "No adb device available. Connect the phone or set PHONE_SERIAL." >&2 + exit 1 + } +} + +timestamp() { + date -u +"%Y%m%dT%H%M%SZ" +} + +start_capture() { + require_adb + local dir="$ARTIFACT_BASE/health-connect-$(timestamp)" + mkdir -p "$dir" + + adb devices -l >"$dir/adb-devices.txt" + adb_cmd shell getprop ro.build.fingerprint >"$dir/phone-build-fingerprint.txt" + adb_cmd shell dumpsys package "$PACKAGE_NAME" >"$dir/package-dumpsys-before.txt" || true + adb_cmd logcat -c + adb_cmd logcat -v threadtime >"$dir/logcat.txt" 2>&1 & + local pid=$! + echo "$pid" >"$dir/logcat.pid" + + cat >"$dir/steps.md" < Intégrations > Health Connect. +3. Validate the visible initial status. +4. Tap "Autoriser l'accès" or "Gérer les autorisations". +5. Validate the expected path: + - permission sheet opens, or + - settings fallback opens cleanly. +6. Grant or deny permissions according to the scenario under test. +7. Return to GameTime and validate the refreshed status. +8. Start and finish a workout if export-after-workout must be checked. +9. Confirm the final Health Connect export outcome shown by the app. + +## Evidence to collect +- Screenshot(s) of the visible status before and after permission handling. +- Screenshot(s) of Health Connect permission/settings UI if opened. +- Notes on whether the path used the permission contract or settings fallback. +- Result of export-after-workout if exercised. +EOF + + echo "$dir" +} + +stop_capture() { + local dir="${1:-}" + [[ -n "$dir" ]] || { + usage >&2 + exit 2 + } + require_adb + [[ -d "$dir" ]] || { + echo "Artifact directory not found: $dir" >&2 + exit 1 + } + + if [[ -f "$dir/logcat.pid" ]]; then + kill "$(cat "$dir/logcat.pid")" >/dev/null 2>&1 || true + fi + + adb_cmd shell dumpsys package "$PACKAGE_NAME" >"$dir/package-dumpsys-after.txt" || true + adb_cmd shell settings list secure >"$dir/settings-secure.txt" || true + + cat < + +Environment: + PHONE_SERIAL Optional adb serial for the phone under test + ARTIFACT_BASE Optional artifact root + PACKAGE_NAME Optional Android package name (default: com.idea.gametime) +EOF +} + +adb_cmd() { + if [[ -n "$PHONE_SERIAL" ]]; then + adb -s "$PHONE_SERIAL" "$@" + else + adb "$@" + fi +} + +require_adb() { + command -v adb >/dev/null 2>&1 || { + echo "adb not found in PATH." >&2 + exit 1 + } + adb start-server >/dev/null + adb_cmd get-state >/dev/null 2>&1 || { + echo "No adb device available. Connect the phone or set PHONE_SERIAL." >&2 + exit 1 + } +} + +timestamp() { + date -u +"%Y%m%dT%H%M%SZ" +} + +start_capture() { + require_adb + local dir="$ARTIFACT_BASE/import-export-real-$(timestamp)" + mkdir -p "$dir" + + adb devices -l >"$dir/adb-devices.txt" + adb_cmd shell getprop ro.build.fingerprint >"$dir/phone-build-fingerprint.txt" + adb_cmd shell dumpsys package "$PACKAGE_NAME" >"$dir/package-dumpsys-before.txt" || true + adb_cmd logcat -c + adb_cmd logcat -v threadtime >"$dir/logcat.txt" 2>&1 & + echo "$!" >"$dir/logcat.pid" + + cat >"$dir/steps.md" <&2 + exit 2 + } + require_adb + [[ -d "$dir" ]] || { + echo "Artifact directory not found: $dir" >&2 + exit 1 + } + + [[ -f "$dir/logcat.pid" ]] && kill "$(cat "$dir/logcat.pid")" >/dev/null 2>&1 || true + adb_cmd shell dumpsys package "$PACKAGE_NAME" >"$dir/package-dumpsys-after.txt" || true + + cat < + +Environment: + PHONE_SERIAL Optional adb serial for the phone under test + WATCH_SERIAL Optional adb serial for the Wear device under test + ARTIFACT_BASE Optional artifact root + PACKAGE_NAME Optional phone package name + WATCH_PACKAGE_NAME Optional watch package name +EOF +} + +adb_phone() { + if [[ -n "$PHONE_SERIAL" ]]; then + adb -s "$PHONE_SERIAL" "$@" + else + adb "$@" + fi +} + +adb_watch() { + [[ -n "$WATCH_SERIAL" ]] || { + echo "WATCH_SERIAL is required for watch companion QA." >&2 + exit 1 + } + adb -s "$WATCH_SERIAL" "$@" +} + +require_adb() { + command -v adb >/dev/null 2>&1 || { + echo "adb not found in PATH." >&2 + exit 1 + } + adb start-server >/dev/null + adb_phone get-state >/dev/null 2>&1 || { + echo "No phone adb device available." >&2 + exit 1 + } + adb_watch get-state >/dev/null 2>&1 || { + echo "No watch adb device available." >&2 + exit 1 + } +} + +timestamp() { + date -u +"%Y%m%dT%H%M%SZ" +} + +start_capture() { + require_adb + local dir="$ARTIFACT_BASE/watch-companion-$(timestamp)" + mkdir -p "$dir" + + adb devices -l >"$dir/adb-devices.txt" + adb_phone shell getprop ro.build.fingerprint >"$dir/phone-build-fingerprint.txt" + adb_watch shell getprop ro.build.fingerprint >"$dir/watch-build-fingerprint.txt" + adb_phone shell dumpsys package "$PACKAGE_NAME" >"$dir/phone-package-dumpsys-before.txt" || true + adb_watch shell dumpsys package "$WATCH_PACKAGE_NAME" >"$dir/watch-package-dumpsys-before.txt" || true + adb_phone logcat -c + adb_watch logcat -c + adb_phone logcat -v threadtime >"$dir/phone-logcat.txt" 2>&1 & + echo "$!" >"$dir/phone-logcat.pid" + adb_watch logcat -v threadtime >"$dir/watch-logcat.txt" 2>&1 & + echo "$!" >"$dir/watch-logcat.pid" + + cat >"$dir/steps.md" <&2 + exit 2 + } + require_adb + [[ -d "$dir" ]] || { + echo "Artifact directory not found: $dir" >&2 + exit 1 + } + + [[ -f "$dir/phone-logcat.pid" ]] && kill "$(cat "$dir/phone-logcat.pid")" >/dev/null 2>&1 || true + [[ -f "$dir/watch-logcat.pid" ]] && kill "$(cat "$dir/watch-logcat.pid")" >/dev/null 2>&1 || true + + adb_phone shell dumpsys package "$PACKAGE_NAME" >"$dir/phone-package-dumpsys-after.txt" || true + adb_watch shell dumpsys package "$WATCH_PACKAGE_NAME" >"$dir/watch-package-dumpsys-after.txt" || true + + cat <