Correction : les rappels SONT natifs, j'avais cherché le mauvais plugin

La version précédente de § 5.1bis affirmait que « la chaîne de notifications
natives n'existe pas de bout en bout ». C'est faux. web/static/local-
notifications.js programme bien, via Capacitor.Plugins.LocalNotifications, le
rappel de séance non faite, le résumé du jour, l'hydratation à 10/13/16 h et le
coucher à 23 h. Le README a donc raison sur le fond ; il attribue seulement la
fonction au mauvais plugin (local-notifications, pas push-notifications).

La méthode qui a produit l'erreur vaut d'être notée, et elle est notée dans le
document : j'avais grepé PushNotifications sans greper LocalNotifications.
Conclure d'un grep négatif qu'une fonctionnalité est absente suppose d'avoir
cherché le bon terme — c'est la même faute que celle qui fait dire à un cron
« rien de neuf ».

Ce qui reste : le chemin ntfy (push_notify.py, api_notifications.py,
tools/notify_morning.py) est résiduel et double une fonction déjà rendue en
natif ; plus aucune notification n'est censée y passer. Et le plugin
@capacitor/push-notifications reste installé avec son entitlement aps-
environment alors que rien ne l'appelle — 2.3.1(a).

⚠️ Ne rien supprimer avant d'avoir vérifié le cron notify_morning sur nexus :
le retirer sous un cron vivant le casserait, et un cron cassé a déjà tenu
quatre mois ici sans être vu. La vérif n'a pas pu être faite depuis le
conteneur de dev (pas de résolution DNS pour nexus) ; la commande est dans le
document.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sylvain Bettinelli
2026-09-22 07:00:49 +00:00
parent a29569c05c
commit c16b92ce29

View File

@@ -244,40 +244,58 @@ du device comme *nom de topic*. L'en-tête du fichier annonce « V2+ : remplacer
par APNs (iOS) + FCM (Android) » — ce n'est pas fait. Voir §5.1bis, qui est le
vrai sujet.
### 5.1bis [vérifié] La chaîne de notifications push natives n'existe pas de bout en bout
### 5.1bis [vérifié] Les rappels sont natifs et fonctionnent ; c'est le chemin ntfy qui est résiduel
Trois constats, chacun vérifié par recherche dans les deux dépôts :
⚠️ **Correction d'une première version de cette section, qui affirmait que « la
chaîne de notifications natives n'existe pas ». C'était faux**, et la méthode
qui a produit l'erreur mérite d'être notée : j'avais cherché
`PushNotifications` (le plugin *distant*) sans chercher `LocalNotifications`.
Conclure d'un grep négatif qu'une fonctionnalité est absente suppose d'avoir
cherché le bon terme.
1. `web/push_notify.py:47-52` — le canal est **ntfy**. `platform == "web"`
rend `False` (« Web Push : à implémenter (V2) »).
2. **Aucun enregistrement de token APNs côté serveur.** Recherche de
`registerToken` / `/api/devices` / `device_token` dans `web/` : **zéro
résultat**.
3. **Le web n'appelle jamais `PushNotifications`** de Capacitor. Recherche dans
`web/**/*.js` et `web/**/*.html` : **zéro résultat**.
**Ce qui marche, en natif** — `web/static/local-notifications.js` programme via
`Capacitor.Plugins.LocalNotifications` :
Côté natif, tout est pourtant en place : `@capacitor/push-notifications` est
installé, `aps-environment` est déclaré, `UIBackgroundModes` contient
`remote-notification`. **La moitié native est prête et personne ne la branche.**
Pour recevoir un rappel, l'utilisateur doit installer l'app **ntfy** et
s'abonner à un topic — ce n'est pas une notification de l'app.
- rappel « Séance pas encore faite » (l. 97) ;
- résumé du jour : sport + durée, « Jour OFF », « Peu récupéré » (l. 150-171) ;
- hydratation à 10 h / 13 h / 16 h (l. 184) ;
- « Heure de te coucher ? » à 23 h (l. 197).
Deux conséquences :
Ce sont de vraies notifications locales iOS, planifiées sur l'appareil, sans
serveur. **Le README a donc raison sur le fond** (les rappels de séance sont
natifs), mais il attribue la fonction au mauvais plugin : c'est
`@capacitor/local-notifications` qui la rend, pas
`@capacitor/push-notifications`.
- **Le README se trompe.** Il liste « ✅ Push notifications natives (rappel
séances) — implémenté côté iOS » **dans la section anti-rejet Guideline
4.2**. C'est le premier argument de la liste, et il ne tient pas : un
examinateur qui teste les rappels ne verra rien. Or 4.2 est précisément le
risque de cette architecture wrapper (§5.3).
- **Une capability déclarée et inutilisée** est au mieux inerte. Apple 2.3.1(a) :
« Don't include any hidden, dormant, or undocumented features in your app ».
**Ce qui reste du chemin ntfy** — `web/push_notify.py` envoie via ntfy (le
`token` du device sert de *nom de topic*), et il a deux appelants vivants :
**Décision à prendre**, et elle est produit avant d'être technique : soit
brancher la chaîne APNs (demande de permission + récupération du token côté
web, endpoint d'enregistrement, envoi via APNs côté serveur), soit assumer ntfy
et **retirer le plugin, l'entitlement et la ligne du README**. La situation
actuelle — déclarer une capability qu'on n'utilise pas et l'annoncer comme
implémentée — est la seule qui cumule les inconvénients des deux.
| Appelant | Ce qu'il expose |
|---|---|
| `web/routers/api_notifications.py:16` | `POST /register-device`, `GET /devices`, `DELETE /devices/{id}`, `POST /test` |
| `tools/notify_morning.py:24` | notification matinale, déclenchée par cron |
L'intention est que **plus rien ne passe par ntfy** (confirmé par Sylvain le
2026-09-22). Ce chemin est donc du code résiduel qui double une fonction déjà
assurée en natif.
⚠️ **Ne pas supprimer avant d'avoir vérifié le cron sur nexus.** Si
`notify_morning.py` y est encore planifié, retirer le module casserait le cron
— et un cron cassé dans ce projet a déjà tenu quatre mois sans être vu. La
vérification n'a **pas** pu être faite depuis le conteneur de dev (pas de
résolution DNS pour `nexus`) :
```
ssh nexus "crontab -l | grep -i notify; systemctl list-timers --all | grep -i notify"
```
**Ce qui reste vrai de la remarque App Store** : `@capacitor/push-notifications`
est installé et `aps-environment` déclaré, alors que **rien n'appelle ce
plugin** (aucun enregistrement de token APNs côté serveur, aucun appel
`PushNotifications` côté web). Une capability déclarée sans usage tombe sous
2.3.1(a) (« hidden, dormant, or undocumented features »). Les rappels étant
couverts par les notifications locales, le plus simple est de **retirer le
plugin distant et l'entitlement** — sauf si des push serveur sont prévues.
### 5.2 [doc] Ce qu'Apple exige, et où on en est
@@ -504,10 +522,11 @@ chiffre mort :**
**Avant soumission :**
9. **Trancher la question des push (§5.1bis)** — brancher APNs, ou assumer ntfy
et retirer plugin + entitlement + la ligne du README. C'est une décision
produit, et elle conditionne l'argument anti-4.2. Puis vérifier
`aps-environment` dans le Summary de l'archive (§5.1).
9. **Nettoyer le résiduel de notifications (§5.1bis)** — vérifier le cron
`notify_morning` sur nexus, puis retirer le chemin ntfy et le plugin
`@capacitor/push-notifications` + son entitlement, que rien n'appelle.
Corriger la ligne du README qui attribue les rappels au mauvais plugin.
Puis vérifier `aps-environment` dans le Summary de l'archive (§5.1).
10. Nutrition labels, Notes for Review nommant les fonctions natives, compte de
démo avec backend allumé (§5.2).