Corrigé (audit) : - cutoffHours : garde hasModel pour ESE (parité Kotlin) — un backup importé ESE + ester non couvert levait TypeError → écran vide - min/max en une passe : les spreads Math.min(...allPoints) levaient RangeError au-delà de ~1e5 arguments (Nuage × zoom max) et allouaient par frame - init MCMC non bloquante : data-ready garantit désormais « asset chargé » Perf (portage v1.8.2 Android, fin de la dérive de miroir) : - prepareE2Context/e2AtCtx : doses groupées, cutoffs précalculés, Bateman paresseux ; computeCurve ne recalcule plus cutoffHours par point - résultat identique (175 tests verts) E2E : version lue via data-version (anti-bug v1.9.3) Docs/commentaires : pk-engine (ESE analytique), pk-calibration (JSDoc arrondi), dialogs (ESE=6), lab-timing (import mort, JSDoc orpheline), home (COLORS), pk-profile-store (test-only), pk_profiles.json exclu du zip (export-ignore, −548 Ko)
200 lines
9.2 KiB
Markdown
200 lines
9.2 KiB
Markdown
# HormoneTrack Web
|
||
|
||
> **La version navigateur d'HormoneTrack** — suivi de thérapie hormonale (THS)
|
||
> avec courbes estimées heure par heure, 100 % locale : **l'app tourne
|
||
> entièrement dans ton navigateur et tes données ne quittent jamais ta
|
||
> machine** (localStorage). Aucun compte, aucun serveur applicatif, aucune
|
||
> télémétrie.
|
||
>
|
||
> C'est le portage fidèle de l'**app Android** — les sauvegardes JSON sont
|
||
> **interchangeables dans les deux sens**. L'app Android vit dans son propre
|
||
> dépôt : [gitea.cloudyfy.fr/Siphonight/HormoneTrack](https://gitea.cloudyfy.fr/Siphonight/HormoneTrack)
|
||
> (README, docs et releases APK).
|
||
> La doc de développement : [docs/DEVELOPPEMENT.md](docs/DEVELOPPEMENT.md).
|
||
|
||
> **⚠️ Avertissement médical** : les courbes sont des **estimations
|
||
> pharmacocinétiques** à titre informatif — ce ne sont pas des mesures.
|
||
> Fie-toi toujours à tes analyses de sang et aux consignes de ton
|
||
> endocrinologue.
|
||
|
||
- **Statut** : web v1.9.5 — parité fonctionnelle avec l'Android v1.9.5
|
||
(modèle Estrannaise analytique + nuage d'incertitude MCMC exclusif ESE ;
|
||
presets des 6 esters injectables ESE ; l'auto-backup journalier Android
|
||
reste structurellement non porté, cf §12 — l'export manuel couvre la
|
||
donnée) ·
|
||
**175 tests verts** · E2E navigateur ✅ · conteneur testé en
|
||
configuration durcie ✅ · lint/i18n ✅
|
||
- **Journal des versions web** : [docs/CHANGELOG.md](docs/CHANGELOG.md)
|
||
- **Releases** : [gitea.cloudyfy.fr/Siphonight/HormoneTrack-web/releases](https://gitea.cloudyfy.fr/Siphonight/HormoneTrack-web/releases)
|
||
(zip de déploiement statique vérifié par téléchargement)
|
||
- **Versionnage** : les versions web sont **alignées sur l'Android porté**
|
||
(web v1.4.10 = toutes les fonctionnalités de l'Android v1.4.10, sauf les
|
||
impossibilités structurelles du navigateur) — cf
|
||
[docs/DEVELOPPEMENT.md §3](docs/DEVELOPPEMENT.md).
|
||
|
||
---
|
||
|
||
## Démarrage rapide
|
||
|
||
### Avec le serveur de développement intégré
|
||
|
||
```bash
|
||
cd web
|
||
python3 scripts/serve.py # → http://127.0.0.1:8970/
|
||
```
|
||
|
||
Ouvre **http://127.0.0.1:8970/** dans ton navigateur. C'est tout.
|
||
|
||
- **Mode démo** (données de test, hook documenté) :
|
||
<http://127.0.0.1:8970/?demo=1> — charge 12 injections + 6 prises de sang
|
||
fictives si le stockage est vide, avec une bannière explicite.
|
||
- ⚠️ L'app doit être servie en HTTP : l'ouverture directe du `index.html`
|
||
en `file://` est bloquée par les navigateurs (modules ES).
|
||
|
||
### Avec n'importe quel serveur statique
|
||
|
||
Le dépôt est un site statique autonome — déploie-le tel quel
|
||
(nginx, caddy, Pages Gitea/GitLab, un NAS…) :
|
||
|
||
```bash
|
||
# nginx (extrait)
|
||
server {
|
||
root /var/www/hormonetrack; # = le contenu de ce dépôt
|
||
index index.html;
|
||
}
|
||
```
|
||
|
||
### Avec Docker (self-host NAS/VPS)
|
||
|
||
L'image ne fait **que servir les fichiers** : aucune donnée dedans, la vie
|
||
privée est identique (les données vivent dans les navigateurs). Deux
|
||
procédures équivalentes — **l'image doit être pour l'arch CPU de l'hôte**
|
||
(« exec format error » = arch incompatible, cf
|
||
[docs/DEVELOPPEMENT.md §10](docs/DEVELOPPEMENT.md)) :
|
||
|
||
```bash
|
||
# ── Option 1 (recommandée) : build SUR le serveur cible
|
||
git clone https://gitea.cloudyfy.fr/Siphonight/HormoneTrack-web && cd HormoneTrack-web
|
||
docker compose up -d --build # arch native, toujours correcte
|
||
|
||
# ── Option 2 : multi-arch depuis un Mac (push vers ton registry)
|
||
docker buildx build --platform linux/amd64,linux/arm64 \
|
||
-t tonuser/hormonetrack-web:latest --push .
|
||
```
|
||
|
||
- Image **non privilégiée** (`nginx-unprivileged`, utilisateur 101, port
|
||
8080), filesystem en **lecture seule** + tmpfs (composé durci), vérif
|
||
healthcheck intégrée, gzip sur l'asset PK (550 Ko → ~150 Ko).
|
||
- Headers `no-cache` : une mise à jour d'image est prise en compte au
|
||
rechargement suivant, sans code périmé chez les clients.
|
||
- Validation en 3 commandes sur l'hôte qui a Docker (cf
|
||
[docs/DEVELOPPEMENT.md §10](docs/DEVELOPPEMENT.md)) : build, run, puis
|
||
`HRT_E2E_BASE=http://127.0.0.1:8080 node scripts/e2e.mjs` — le même test
|
||
E2E que le CI pilote le site SERVI PAR LE CONTENEUR. Pour tester l'arch
|
||
cible AVANT déploiement :
|
||
`bash scripts/container-test.sh 8979 linux/amd64`.
|
||
|
||
Aucun build, aucune variable d'environnement, aucun composant serveur : les
|
||
données de chaque personne vivent **dans SON navigateur**, jamais sur la
|
||
machine qui sert les fichiers.
|
||
|
||
## Fonctionnalités (à l'image de l'app Android)
|
||
|
||
- **Courbes estimées heure par heure** : E2 (pg/mL) et T (ng/mL), vues
|
||
24 h / 7 j / 30 j, **zoom** (pinch, molette, boutons − / +, 6 h → 300 j,
|
||
échantillonnage adaptatif), **panoramique** (glisser droite = passé,
|
||
gauche = futur avec la prévision), **pics & creux** avec valeurs estimées.
|
||
- **Trois modèles PK superposables** : **Estrannaise** (tables du `.ods`),
|
||
**Transfem Science** (méta-analyse V3C, 7 esters), **WHSAH** (fit Mona,
|
||
6 esters) — toggles indépendants, calibrés séparément.
|
||
- **Modèle Bateman** paramétrable pour gel, patch et voie orale.
|
||
- **Simulation prévisionnelle** (Posologie) : projection des doses à venir,
|
||
extension de fenêtre sans saut, horizon jusqu'à 1 an, marqueurs de doses.
|
||
- **Log des doses** avec override d'ester par injection, édition, Δ jours
|
||
entre doses, temps sous THS.
|
||
- **Analyses de sang** E2 + T en une entrée, unités T multiples
|
||
(ng/mL, ng/dL, ng/L, nmol/L).
|
||
- **Calibration** par période d'ester et **par modèle affiché**
|
||
(auto-calibration optionnelle, désactivée par défaut + bouton manuel).
|
||
- **Seuils d'alerte** configurables (E2/T haut/bas) avec notification
|
||
navigateur et anti-spam.
|
||
- **« Tracé labs » (v1.5.0)** : courbe hybride ancrée sur tes labs
|
||
(chip `Tracé labs`, off par défaut) — miroir strict de l'Android v1.5.0
|
||
- **Rappels** via les notifications du navigateur (actions « Loguer
|
||
maintenant » / « Reporter 1 h ») — tant que la page est ouverte, cf
|
||
[limites](#limites-vs-lapp-android).
|
||
- **Sauvegarde/Restauration JSON** compatible Android (import en mode
|
||
écrasement, réglages transportés).
|
||
- **Logs de diagnostic** exportables (Paramètres) pour le debug à distance.
|
||
- **FR + EN** (langue par app, indépendante du système), dialog
|
||
« Nouveautés » après mise à jour.
|
||
|
||
## Vie privée
|
||
|
||
- **100 % local** : les données (traitements, doses, analyses, réglages)
|
||
vivent dans le **localStorage de ton navigateur**, sur TA machine. Le
|
||
serveur qui sert l'app ne voit rien, ne stocke rien.
|
||
- Les seules requêtes réseau sont des **lectures** de fichiers statiques
|
||
(l'asset des profils PK, le changelog) — aucune donnée personnelle
|
||
n'est jamais envoyée.
|
||
- Sauvegarde = un fichier JSON que tu stockes où tu veux.
|
||
- `?demo=1` charge des données FICTIVES clairement banniérées, jamais
|
||
automatiquement.
|
||
|
||
## Compatibilité avec l'app Android
|
||
|
||
| Flux | Support |
|
||
|---|---|
|
||
| Export Android → import web | ✅ (backups v1 et v2 — testés sur de vrais exports) |
|
||
| Export web → import Android | ✅ (même schéma BackupData v2, champs Gson identiques) |
|
||
| Modèles PK / courbes | ✅ mêmes maths, mêmes paramètres, mêmes pins de tests |
|
||
| Calibrations (facteurs, k) | ✅ recalculées identiquement depuis les labs |
|
||
|
||
Le schéma de backup est verrouillé par des tests des deux côtés
|
||
(`tests/backup.test.js` ↔ `BackupGsonTest.kt` Android) — toute divergence
|
||
métadonnée↔code ferait échouer la CI.
|
||
|
||
## Limites vs l'app Android
|
||
|
||
| Fonctionnalité | Android | Web |
|
||
|---|---|---|
|
||
| Rappels app fermée | ✅ (AlarmManager) | ❌ page ouverte uniquement (pas de scheduler système) |
|
||
| Événements d'agenda récurrents | ✅ | ❌ impossible dans un navigateur (pas de CalendarProvider) |
|
||
| Montre (Gadgetbridge) | ✅ notifications miroir | ❌ |
|
||
| Verrou biométrique / widget | roadmap | ❌ |
|
||
|
||
Ces limites sont structurelles (plateforme navigateur), pas des choix de
|
||
design — elles sont listées dans le dialog « Nouveautés » et la doc de dev.
|
||
|
||
## FAQ
|
||
|
||
**Mes données sont-elles visibles par le serveur qui héberge l'app ?**
|
||
Non. Le serveur ne fait que distribuer des fichiers statiques (comme des
|
||
images). Tes données vivent dans ton navigateur et n'en sortent jamais.
|
||
|
||
**Je change de navigateur / d'ordinateur, je fais quoi ?**
|
||
Paramètres → « Exporter JSON » sur la première machine, « Importer JSON »
|
||
sur la seconde. Le backup transporte tout (données + réglages).
|
||
|
||
**Puis-je utiliser Android et web en parallèle ?**
|
||
Oui — exporte/importe entre les deux. Attention : l'import est un
|
||
écrasement (comme sur Android), pas une fusion.
|
||
|
||
**Pourquoi l'app me demande-t-elle la permission « Notifications » ?**
|
||
Pour les rappels de dose. Refuser n'empêche rien d'autre (la bannière
|
||
in-app s'affiche quand même à l'heure du rappel, page ouverte).
|
||
|
||
## Doc de développement
|
||
|
||
Architecture, portage fichier par fichier, format du backup, processus de
|
||
test (132 tests Node + E2E navigateur), processus de push et pièges connus :
|
||
**[docs/DEVELOPPEMENT.md](docs/DEVELOPPEMENT.md)**.
|
||
|
||
## Licence
|
||
|
||
**GPL-3.0** — voir [LICENSE](LICENSE), cohérente avec l'app Android
|
||
et l'écosystème Gadgetbridge. Les modèles PK appartiennent à leurs autrices
|
||
respectives ([Estrannaise](https://estrannaise.github.io/),
|
||
[Transfem Science](https://transfemscience.org),
|
||
[WHSAH Collective via Mona](https://github.com/mona-hrt/mona)).
|