feat: authentification QR code / token pour Pronote #6

Open
AntoineVe wants to merge 1 commits from feat/qr-token-auth into main
Owner

Summary

Ajoute le mode d'authentification PRONOTE_AUTH_MODE=qr_token comme alternative au mode password pour les instances Pronote utilisant HubEduConnect/EduConnect où l'authentification par mot de passe échoue (CAPTCHA, MFA, flux SAML modifié). Le pipeline s'enrôle via QR code puis persiste un token rotatif entre les exécutions. En cas d'échec de rotation, l'utilisateur est notifié via XMPP.

Changes

  • PronoteSettings : nouveaux champs auth_mode (password | qr_token), qr_code_file, qr_pin (SecretStr)
  • PronoteAuthState (nouveau module) : persistance du token rotatif dans .pronote_auth_state.json — écriture atomique, permissions 0600 dès la création, symlink-safe (O_EXCL + O_NOFOLLOW)
  • PronoteClient._connect() : branching password / qr_tokentoken_login avec creds persistés, qrcode_login pour l'enrôlement initial, export_credentials persisté après chaque login réussi
  • PronoteAuthRotationError (nouvelle erreur) : levée en cas d'échec de rotation du token, propagée sans wrapping à travers PronoteFetcher et fetch_step jusqu'à PipelineRunner.run() qui notifie via XMPP (si canal disponible et dry_run inactif)
  • _is_pronotepy_configured() mode-aware : qr_token ne requiert que PRONOTE_URL
  • _collect_auth_secrets() : redaction des secrets explicites (token, PIN, jeton QR) dans tous les logs du chemin d'authentification
  • .env.example : PRONOTE_AUTH_MODE, PRONOTE_QR_CODE_FILE, PRONOTE_QR_PIN
  • AGENTS.md : contrat d'authentification QR code / token
  • Wiki GuidePronote : section enrôlement, exécutions suivantes, ré-enrôlement manuel

Tests

686 tests passés, couverture 94.87%. 35 tests QR/token dédiés :

  • 5 tests config QR (mode, PIN SecretStr, redaction)
  • 9 tests auth_state (round-trip, corruption, permissions 0600, non-fuite)
  • 10 tests client QR (token_login, qrcode_login, rotation, secrets)
  • 3 tests propagation (PronoteFetcher, fetch_step — vraie chaîne)
  • 4 tests intégration rotation end-to-end (XMPP, dry_run, no-channel, non-fuite)
  • 4 tests fallback mode-aware

Checklist

  • Tests ajoutés (35 nouveaux tests QR/token)
  • Documentation mise à jour (.env.example, AGENTS.md, wiki GuidePronote)
  • Aucun changement cassant pour le mode password (défaut inchangé)
  • ruff check . | ruff format --check . | mypy . | bandit

Breaking changes

Aucune. Le mode password reste le défaut inchangé. Les déploiements existants ne nécessitent aucune modification de configuration.

Notes

  • Test en production requis avant tag v0.1.2 (per AGENTS.md §13) : générer un QR code frais depuis l'app mobile Pronote, configurer PRONOTE_AUTH_MODE=qr_token + PRONOTE_QR_CODE_FILE + PRONOTE_QR_PIN, lancer le pipeline.
  • Le QR code expire ~10 minutes après génération.
  • Le token rotate à chaque session — .pronote_auth_state.json est mis à jour automatiquement après chaque login réussi.
## Summary Ajoute le mode d'authentification `PRONOTE_AUTH_MODE=qr_token` comme alternative au mode `password` pour les instances Pronote utilisant HubEduConnect/EduConnect où l'authentification par mot de passe échoue (CAPTCHA, MFA, flux SAML modifié). Le pipeline s'enrôle via QR code puis persiste un token rotatif entre les exécutions. En cas d'échec de rotation, l'utilisateur est notifié via XMPP. ## Changes - **`PronoteSettings`** : nouveaux champs `auth_mode` (`password` | `qr_token`), `qr_code_file`, `qr_pin` (SecretStr) - **`PronoteAuthState`** (nouveau module) : persistance du token rotatif dans `.pronote_auth_state.json` — écriture atomique, permissions `0600` dès la création, symlink-safe (`O_EXCL` + `O_NOFOLLOW`) - **`PronoteClient._connect()`** : branching `password` / `qr_token` — `token_login` avec creds persistés, `qrcode_login` pour l'enrôlement initial, `export_credentials` persisté après chaque login réussi - **`PronoteAuthRotationError`** (nouvelle erreur) : levée en cas d'échec de rotation du token, propagée **sans wrapping** à travers `PronoteFetcher` et `fetch_step` jusqu'à `PipelineRunner.run()` qui notifie via XMPP (si canal disponible et `dry_run` inactif) - **`_is_pronotepy_configured()`** mode-aware : `qr_token` ne requiert que `PRONOTE_URL` - **`_collect_auth_secrets()`** : redaction des secrets explicites (token, PIN, jeton QR) dans tous les logs du chemin d'authentification - **`.env.example`** : `PRONOTE_AUTH_MODE`, `PRONOTE_QR_CODE_FILE`, `PRONOTE_QR_PIN` - **`AGENTS.md`** : contrat d'authentification QR code / token - **Wiki `GuidePronote`** : section enrôlement, exécutions suivantes, ré-enrôlement manuel ## Tests 686 tests passés, couverture 94.87%. 35 tests QR/token dédiés : - 5 tests config QR (mode, PIN SecretStr, redaction) - 9 tests auth_state (round-trip, corruption, permissions 0600, non-fuite) - 10 tests client QR (token_login, qrcode_login, rotation, secrets) - 3 tests propagation (PronoteFetcher, fetch_step — vraie chaîne) - 4 tests intégration rotation end-to-end (XMPP, dry_run, no-channel, non-fuite) - 4 tests fallback mode-aware ## Checklist - [x] Tests ajoutés (35 nouveaux tests QR/token) - [x] Documentation mise à jour (.env.example, AGENTS.md, wiki GuidePronote) - [x] Aucun changement cassant pour le mode `password` (défaut inchangé) - [x] `ruff check .` ✅ | `ruff format --check .` ✅ | `mypy .` ✅ | `bandit` ✅ ## Breaking changes Aucune. Le mode `password` reste le défaut inchangé. Les déploiements existants ne nécessitent aucune modification de configuration. ## Notes - **Test en production requis** avant tag `v0.1.2` (per AGENTS.md §13) : générer un QR code frais depuis l'app mobile Pronote, configurer `PRONOTE_AUTH_MODE=qr_token` + `PRONOTE_QR_CODE_FILE` + `PRONOTE_QR_PIN`, lancer le pipeline. - Le QR code expire ~10 minutes après génération. - Le token rotate à chaque session — `.pronote_auth_state.json` est mis à jour automatiquement après chaque login réussi.
AntoineVe added 1 commit 2026-09-08 23:17:54 +02:00
Ajoute le mode d'authentification PRONOTE_AUTH_MODE=qr_token comme alternative
au mode password pour les instances Pronote utilisant HubEduConnect/EduConnect
où l'authentification par mot de passe échoue (CAPTCHA, MFA, flux SAML).

Nouveaux éléments :
- PronoteSettings : auth_mode, qr_code_file, qr_pin (SecretStr)
- PronoteAuthState : persistance du token rotatif dans .pronote_auth_state.json
  (écriture atomique, permissions 0600, symlink-safe via O_EXCL|O_NOFOLLOW)
- PronoteClient._connect_qr_token() : token_login avec creds persistés,
  qrcode_login pour l'enrôlement initial, export_credentials persisté après
  chaque login réussi
- PronoteAuthRotationError : levée en cas d'échec de rotation du token,
  propagée sans wrapping à travers PronoteFetcher et fetch_step jusqu'à
  PipelineRunner.run() qui notifie via XMPP (si canal disponible et dry_run inactif)
- _is_pronotepy_configured() mode-aware : qr_token ne requiert que PRONOTE_URL
- _collect_auth_secrets() : redaction des secrets explicites (token, PIN, jeton QR)
  dans tous les logs du chemin d'authentification

Documentation :
- .env.example : PRONOTE_AUTH_MODE, PRONOTE_QR_CODE_FILE, PRONOTE_QR_PIN
- AGENTS.md : contrat d'authentification QR code / token
- Wiki GuidePronote : section enrôlement, exécutions suivantes, ré-enrôlement

Tests (686 passés, couverture 94.87%) :
- 5 tests config QR, 9 tests auth_state, 10 tests client QR, 3 tests propagation,
  4 tests intégration rotation end-to-end, 4 tests fallback mode-aware
- Tests de non-fuite : sentinelles distinctes pour token, PIN, jeton QR

Co-authored-by: coder/litellm/coder <coder@agents.invalid>
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/qr-token-auth:feat/qr-token-auth
git checkout feat/qr-token-auth
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: AntoineVe/college-infos#6