Le refresh token est rotatif : la chaîne se régénère seule indéfiniment tant que
le nouveau token est persisté. La reconnexion manuelle n'était requise que lorsque
cet invariant cassait. Trois correctifs :
- Refresh PROACTIF : on rafraîchit dès qu'il reste < 2h sur le token (~8h de vie)
au lieu des 2 dernières minutes. Un échec transitoire a des heures de marge avant
que l'access token meure ; la fenêtre où un kill/timeout perd le token rotatif
fraîchement rotaté passe de ~8h à quelques ms. Réglable via
MONITORINK_CLAUDE_REFRESH_LEAD_MIN (défaut 120).
- Distinction FATAL vs TRANSITOIRE : 400 invalid_grant / 401 sur l'endpoint token
-> _RefreshFatal, sans backoff ni re-soumission en boucle (évite la reuse-detection
qui révoque toute la famille). 429/5xx/réseau gardent le backoff exponentiel.
- Visibilité + auto-réparation : le cas fatal affiche "Reconnexion Claude requise"
(pas de repli cache silencieux) et l'alerte se referme seule dès qu'un token frais
réapparaît sur disque (re-login isolé), sans redémarrer le conteneur.
Timeout du POST de refresh porté à 45s (réglable, MONITORINK_CLAUDE_REFRESH_TIMEOUT)
pour réduire la fenêtre de perte du token après rotation serveur.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le token d'accès vit ~8h ; à expiration, fetch_usage retentait un refresh à
chaque rendu (~15min) avec un backoff fixe de 5min toujours déjà expiré. Chaque
tentative re-saturait le rate-limit /v1/oauth/token -> 429 en boucle (>15h
observé), token jamais rafraîchi, usage figé sur la dernière valeur en cache.
- backoff exponentiel 10min -> 6h (au lieu de 5min fixes), réinitialisé sur succès
- respect de l'en-tête Retry-After quand il dépasse le palier
- logging succès/échec du refresh (le chemin n'en avait aucun -> diag à l'aveugle)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lecture des tuiles Upload/Download de /account/ (libellés Go/To gardés tels quels
via up_str/down_str pour conserver les décimales). Condition io -> has_io.
Type yggreborn : login form classique (identifier=EMAIL, password, csrf_token),
ratio lu dans l'en-tête (Ratio : X.XX). Pas de up/down ni jetons (ligne envoyé/
reçu rendue conditionnelle sur up/down>0).
Champ tokens optionnel sur TrackerStat (None = tracker sans jetons) ; torr9 le
remplit depuis jeton_balance de /users/me. Ligne « N jetons » conditionnelle sous
envoyé/reçu, masquée pour les trackers sans système de jetons (c411).
torr9 a une API Go dédiée (api.torr9.net) avec auth JWT (username/password).
Le ratio se calcule (total+bonus) up/down comme le frontend ; pas de champ
ratio dans l'API. Le passkey du compte ne sert qu'au RSS, pas au profil.
Nouveau module integrations/trackers.py : pour chaque tracker configuré (env
MONITORINK_TRACKERS + bloc par clé), récupère ratio/uploaded/downloaded. Type
unit3d_nuxt (c411) : login session (CSRF meta + /api/auth/login) car le ratio
n'est pas lisible au token API ; session réutilisée, résultat caché (TTL 30 min).
Section dashboard sous le NAS, style instrument 1-bit. Architecture par type pour
ajouter d'autres trackers ensuite.
Token expiré -> refresh tenté à chaque rendu, échec non mémorisé -> on martelait
platform.claude.com et le 429 s'entretenait. On impose désormais un backoff de 5 min
après un refresh échoué (et sur la voie de refresh forcé 401), pendant lequel on sert
la dernière valeur connue au lieu de re-tenter.
Backend : endpoints /frame.meta (ligne 'MODE X Y W H SEQ') + /frame.png qui
servent un crop de la zone modifiée (diff PIL par client) ou l'image pleine.
Full refresh forcé tous les N cycles (MONITORINK_FULL_EVERY=12, ~1h) ou si la
zone change sur plus de 60% de l'écran. Mode 'noop' quand rien ne change.
Anti-429 : l'usage Claude est mis en cache (MONITORINK_USAGE_TTL=120s) avec
repli sur la dernière valeur connue en cas d'erreur transitoire.
Kobo : monitorinkloop.sh récupère meta puis png et fait un fbink partiel
(-g file=,x=,y=) sans flash, full refresh (-c -f) en mode full. Refresh 5 min.