Conteneurisation (site 100 % statique — l'image ne détient AUCUNE donnée, vie privée identique) : - Dockerfile : nginxinc/nginx-unprivileged:alpine (uid 101, port 8080, pas de root), healthcheck wget intégré, labels OCI - nginx.conf : no-cache systématique (cohérence du jeu de fichiers à chaque mise à jour d'image, coût nul : ~600 Ko + gzip sur l'asset PK), gzip, en-têtes de sécurité, deny des dotfiles - .dockerignore : runtime uniquement (docs/ inclus — dialog changelog) ; local-test-data exclu en filet de sécurité - docker-compose.yml : read_only + tmpfs (/var/cache/nginx, /run, /tmp — les temporaires de nginx-unprivileged, constat au premier test réel) + no-new-privileges Nouveaux tests avant release : - scripts/container-test.sh : build + run DURCI (config compose) + healthcheck healthy + endpoints 200 + headers (no-cache/nosniff/DENY/ no-referrer) + gzip réel + MIME strict des modules ES + fichiers cachés non servis + image propre (pas de node_modules/npm) + docs/ embarqué + E2E playwright complet CONTRE LE CONTENEUR (HRT_E2E_BASE) - scripts/e2e.mjs : mode externe HRT_E2E_BASE (pilote un site déjà déployé — conteneur inclus, serveur local non démarré) - scripts/check.sh --release : supplée les 9 vérifications (version ↔ changelog ↔ tag ↔ arbre propre + test conteneur si daemon) Runtime Docker local installé pour le CI-like (colima 2 CPU / 2 Go) : premier build + run réel = 2 problèmes testés et corrigés (tmpfs /tmp, key case header_json curl). CONTAINER TEST OK en configuration durcie.
8.0 KiB
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 (README, docs et releases APK). La doc de développement : 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.4.10 — portage de l'Android v1.4.10 · 121 tests verts · E2E navigateur ✅ · lint/i18n ✅
- Journal des versions web : docs/CHANGELOG.md
- 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.
Démarrage rapide
Avec le serveur de développement intégré
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.htmlenfile://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…) :
# 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). Build et exécution :
docker compose up -d # build + run → http://<hôte>:8080/
docker compose up -d --build # rebuild après mise à jour du dépôt
- Image non privilégiée (
nginx-unprivileged, utilisateur 101, port 8080), filesystem en lecture seule (composé prêt pour le NAS), healthcheck intégré, 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) : 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.
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.
- Rappels via les notifications du navigateur (actions « Loguer maintenant » / « Reporter 1 h ») — tant que la page est ouverte, cf limites.
- 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=1charge 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 (121 tests Node + E2E navigateur), processus de push et pièges connus : docs/DEVELOPPEMENT.md.
Licence
GPL-3.0 — voir LICENSE, cohérente avec l'app Android et l'écosystème Gadgetbridge. Les modèles PK appartiennent à leurs autrices respectives (Estrannaise, Transfem Science, WHSAH Collective via Mona).