diff --git a/docs/annex-comparison.tex b/docs/annex-comparison.tex new file mode 100644 index 0000000..5b40ceb --- /dev/null +++ b/docs/annex-comparison.tex @@ -0,0 +1,51 @@ +% ============================================================================= +% ANNEXE B : TABLEAU COMPARATIF SYNTHÉTIQUE +% ============================================================================= + +\chapter{Tableau comparatif synthétique} +\label{annex:comparison} + +\begin{table}[htbp] + \centering + \caption{Comparatif des méthodes d'authentification} + \label{tab:comparison} + \begin{tabularx}{\textwidth}{L{2cm} L{2.5cm} L{2.5cm} L{2cm} L{2cm} L{2.5cm}} + \toprule + \textbf{Méthode} & \textbf{Périmètre} & \textbf{Identifiants} & \textbf{Expiration} & \textbf{Complexité} & \textbf{Statut dans \texttt{pronote-sync}} \\ + \midrule + + \textbf{URL iCal sécurisée} & EDT + devoirs (si inclus dans le flux) & Jeton URL & Longue durée (dépend de l'instance) & Très faible & \emojicheck\ Pris en charge \\ + + \textbf{Connexion directe} (mot de passe + ENT) & Agenda/EDT, devoirs, messages & Identifiant + mot de passe + ENT & Session dépendante de l'instance & Élevée & \emojicheck\ Pris en charge \\ + + \textbf{QR Code + token mobile} & Agenda/EDT, devoirs, messages & PIN 4 chiffres \rightarrow token + UUID & QR ~10 min ({\warningicon\ hypothèse}) ; token dépendant de l'instance & Modérée & \emojicheck\ Pris en charge \\ + + \textbf{SSO ENT (CAS/SAML)} & — & Identifiants ENT & Session ENT & Très élevée & \emojicross\ Non implémenté (seuls les 30 ENT de la liste fermée \texttt{\_ENT\_NAMES} sont supportés via \texttt{pronotepy}) \\ + + \textbf{EduConnect} & — & Identifiants nationaux & Session EduConnect & Très élevée & \emojicross\ Non implémenté \\ + + \textbf{CAS direct} & — & Identifiants CAS & Ticket single-use & Modérée & \emojicross\ Non implémenté \\ + + \textbf{API publique} & N/A & N/A & N/A & N/A & \emojicross\ Inexistante \\ + + \bottomrule + \end{tabularx} +\end{table} + +\section*{Légende} +\addcontentsline{toc}{section}{Légende} + +\begin{itemize} + \item \textbf{Périmètre} : Les méthodes \textbf{iCal} sont en lecture seule (EDT + devoirs si inclus + dans le flux). Les méthodes \textbf{Connexion directe} et \textbf{QR Code + token mobile} + permettent les opérations \texttt{pronotepy} effectivement implémentées par ce projet (agenda, + devoirs, messages ; informations ignorées en mode \texttt{qr\_token}). + \item \textbf{QR ~10 min} : {\warningicon\ \textbf{Hypothèse non vérifiée}} (observé dans + \texttt{pronotepy} via un message d'exception, dépend de l'instance). + \item \textbf{Session dépendante de l'instance} : {\warningicon\ \textbf{Hypothèse non vérifiée}} + (nécessite un essai réel). +\end{itemize} + +% ============================================================================= +% FIN DE L'ANNEXE +% ============================================================================= diff --git a/docs/annex-ecarts.tex b/docs/annex-ecarts.tex new file mode 100644 index 0000000..632e27c --- /dev/null +++ b/docs/annex-ecarts.tex @@ -0,0 +1,62 @@ +% ============================================================================= +% ANNEXE C : ÉCARTS ET NOTES DE COHÉRENCE +% ============================================================================= + +\chapter{Écarts et notes de cohérence} +\label{annex:ecarts} + +\section{Alignement avec \texttt{.env.example}} +\label{sec:alignement-env} + +\begin{table}[htbp] + \centering + \caption{Alignement avec \texttt{.env.example}} + \label{tab:alignement-env} + \begin{tabularx}{\textwidth}{L{4.2cm} L{3.2cm} L{4.4cm} L{2.2cm}} + \toprule + \textbf{Paramètre} & \textbf{Document} & \textbf{Code} & \textbf{Statut} \\ + \midrule + + \texttt{PRONOTE\_ICAL\_URL} & \emojicheck\ Lignes 2, 42--50 & \emojicheck\ \texttt{sources/ical.py} & \textbf{Cohérent} \\ + + \texttt{PRONOTE\_URL} & \emojicheck\ Ligne 3 & \emojicheck\ \texttt{client.py} (ligne 294) & \textbf{Cohérent} \\ + + \texttt{PRONOTE\_ENT} & \emojicheck\ Ligne 7 & \emojicheck\ \texttt{client.py} (ligne 297, \texttt{\_ENT\_NAMES}) & \textbf{Cohérent} \\ + + \texttt{PRONOTE\_AUTH\_MODE=qr\_token} & \emojicheck\ Ligne 23 & \emojicheck\ \texttt{client.py} (ligne 334) & \textbf{Cohérent} \\ + + \texttt{PRONOTE\_QR\_CODE\_FILE} & \emojicheck\ Ligne 24 & \emojicheck\ \texttt{client.py} (ligne 387) & \textbf{Cohérent} \\ + + \texttt{PRONOTE\_QR\_PIN} & \emojicheck\ Ligne 25 & \emojicheck\ \texttt{client.py} (ligne 388) & \textbf{Cohérent} \\ + + \emph{« Le QR code se génère sur le site web »} & \emojicheck\ Ligne 21 & \emojicheck\ Section « Procédure QR pour \texttt{pronote-sync} » & \textbf{Cohérent} \\ + + \bottomrule + \end{tabularx} +\end{table} + +\section{Écarts avec \texttt{docs/exploitation.md}} +\label{sec:ecarts-exploitation} + +\begin{table}[htbp] + \centering + \caption{Écarts avec \texttt{docs/exploitation.md}} + \label{tab:ecarts-exploitation} + \begin{tabularx}{\textwidth}{L{4.2cm} L{2.6cm} L{5cm} L{2.6cm}} + \toprule + \textbf{Élément} & \textbf{\texttt{exploitation.md}} & \textbf{Ce document} & \textbf{Action} \\ + \midrule + + \emph{« Le QR code expire \textasciitilde{}10 minutes »} & Ligne 22 & \warningicon\ \textbf{Hypothèse non vérifiée} (section « Cycle de vie des tokens ») & \textbf{Aucune} (hors périmètre). \\ + + \emph{« Mode \texttt{qr\_token} incompatible avec dry-run »} & Lignes 65--66 & \emojicheck\ Section « Incompatibilités » & \textbf{Cohérent} \\ + + \emph{« Fichier \texttt{.pronote\_auth\_state.json} (mode 0600) »} & Lignes 70--75 & \emojicheck\ Section « Sécurité » & \textbf{Cohérent} \\ + + \bottomrule + \end{tabularx} +\end{table} + +% ============================================================================= +% FIN DE L'ANNEXE +% ============================================================================= diff --git a/docs/annex-libraries.tex b/docs/annex-libraries.tex new file mode 100644 index 0000000..317c6a3 --- /dev/null +++ b/docs/annex-libraries.tex @@ -0,0 +1,34 @@ +% ============================================================================= +% ANNEXE A : BIBLIOTHÈQUES TIERCES +% ============================================================================= + +\chapter{Bibliothèques tierces} +\label{annex:libraries} + +\begin{table}[htbp] + \centering + \caption{Bibliothèques tierces et leur statut dans \texttt{pronote-sync}} + \label{tab:libraries} + \begin{tabularx}{\textwidth}{L{2.5cm} L{1.5cm} L{3cm} L{3cm} L{2.5cm}} + \toprule + \textbf{Bibliothèque} & \textbf{Langage} & \textbf{Dépôt} & \textbf{Méthodes supportées} & \textbf{Statut dans \texttt{pronote-sync}} \\ + \midrule + + \textbf{pronotepy} & Python & \url{https://github.com/bain3/pronotepy} & Connexion directe, QR code/token, \textbf{30 ENT} (liste fermée) & \emojicheck\ \textbf{Dépendance principale} (version \textbf{2.15.7} vérifiée). \\ + + \textbf{pronote-api} & TypeScript & \url{https://github.com/Litarvan/pronote-api} & Connexion directe, CAS, ENT & \emojicross\ Non utilisée. \\ + + \textbf{pronote-qrcode-api} & JavaScript & \url{https://github.com/Androz2091/pronote-qrcode-api} & Déchiffrement QR code & \emojicross\ Non utilisée (intégration native via \texttt{pronotepy}). \\ + + \bottomrule + \end{tabularx} +\end{table} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ Observé dans \texttt{pyproject.toml}} (dépendances) + code source local + (2026-09-12). +\end{infobox} + +% ============================================================================= +% FIN DE L'ANNEXE +% ============================================================================= diff --git a/docs/ch-introduction.tex b/docs/ch-introduction.tex new file mode 100644 index 0000000..4ac785e --- /dev/null +++ b/docs/ch-introduction.tex @@ -0,0 +1,36 @@ +% ============================================================================= +% CHAPITRE : INTRODUCTION +% ============================================================================= + +\chapter{Introduction} +\label{ch:introduction} + +Ce document documente \textbf{uniquement les méthodes d'authentification prises en charge ou + délégables par \texttt{pronote-sync}}, en alignement strict avec : + +\begin{itemize} + \item Le code source de \texttt{pronote\_sync/sources/pronote/client.py} (liste fermée + \texttt{\_ENT\_NAMES}, gestion des tokens). + \item La bibliothèque \texttt{pronotepy} \textbf{2.15.7} (contrat des méthodes + \texttt{qrcode\_login}, \texttt{token\_login}, \texttt{export\_credentials}). + \item Les paramètres de configuration \texttt{.env.example} (lignes 21–25). +\end{itemize} + +\section{Périmètre} + +\begin{itemize} + \item {\emojicheck\ \textbf{Pris en charge}} : Méthodes implémentées et testées dans + \texttt{pronote-sync}. + \item {\emojiinfo\ \textbf{Délégable à pronotepy}} : Méthodes gérées par \texttt{pronotepy} + mais non directement exposées par \texttt{pronote-sync}. + \item {\emojicross\ \textbf{Non implémenté}} : Méthodes non supportées (ex. CAS/SAML + générique, EduConnect direct). +\end{itemize} + +\section{Public cible} + +Développeurs et intégrateurs de \texttt{pronote-sync}. + +% ============================================================================= +% FIN DU CHAPITRE +% ============================================================================= diff --git a/docs/ch-method1.tex b/docs/ch-method1.tex new file mode 100644 index 0000000..31860eb --- /dev/null +++ b/docs/ch-method1.tex @@ -0,0 +1,112 @@ +% ============================================================================= +% CHAPITRE : MÉTHODE 1 — URL ICAL SÉCURISÉE +% ============================================================================= + +\chapter{Méthode 1 : URL iCal sécurisée (\texttt{icalsecurise})} +\label{ch:method1} + +\section{Principe général} + +Pronote expose un flux de calendrier en lecture seule conforme à la norme +\textbf{iCalendar (RFC 5545)}. L'accès est contrôlé par un \textbf{jeton secret} intégré dans +l'URL sous forme de paramètre de requête \texttt{icalsecurise}. + +\begin{infobox} + \textbf{Statut} : {\emojiinfo\ Observé localement} (fonctionnalité native de Pronote, version non spécifiée). +\end{infobox} + +\section{Obtention du jeton} + +\begin{enumerate} + \item Se connecter à Pronote (Espace Parents ou Élève) via n'importe quelle méthode. + \item Accéder à la vue \guillemotleft Emploi du temps \guillemotright. + \item Utiliser la fonction \guillemotleft Export iCal \guillemotright ou \guillemotleft Exporter \guillemotright. + \item Pronote génère une URL contenant un jeton secret \texttt{icalsecurise}. + \item \textbf{Copier cette URL} : elle constitue une crédentiale unique sensible qui doit être + protégée comme un mot de passe. +\end{enumerate} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ Observé localement dans les interfaces Pronote} (version non spécifiée, + hypothèse à valider). + + \textbf{Note} : Les étapes dépendent de l'instance et du type de compte. L'exemple ci-dessus est + non fonctionnel et ne contient aucun secret. +\end{infobox} + +\section{Format de l'URL} + +\begin{lstlisting}[language=bash, caption=Format d'URL iCal Pronote, label=lst:ical-url] +https://{etablissement}.index-education.net/pronote/ical/Edt_{prenom}.ics?icalsecurise={jeton}&version={version}¶m={param} +\end{lstlisting} + +\begin{itemize} + \item \texttt{icalsecurise} : \textbf{Jeton secret} (crédentiale). + \item \texttt{version} : Version de Pronote (ex. \texttt{2024}). + \item \texttt{param} : Paramètres optionnels. +\end{itemize} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ Analysé via \texttt{pronote\_sync/sources/ical.py}}. +\end{infobox} + +\section{Cycle de vie} + +\begin{itemize} + \item \textbf{Pérennité} : Le jeton reste valide jusqu'à : + \begin{itemize} + \item Révocation manuelle par l'utilisateur dans Pronote. + \item Régénération par l'établissement (ex. à la rentrée scolaire). + \end{itemize} + \item {\warningicon\ \textbf{Hypothèse à valider}} : La durée exacte dépend des politiques + de l'établissement (non documentée officiellement). +\end{itemize} + +\begin{infobox} + \textbf{Source} : {\warningicon\ Comportement variable selon les instances} (à tester localement). +\end{infobox} + +\section{Sécurité} + +\begin{enumerate} + \item \textbf{Surface d'attaque} : Le jeton est encodé dans l'URL \rightarrow risque d'exposition via : + \begin{itemize} + \item Logs serveur/proxy. + \item En-tête \texttt{Referer}. + \item Historique du navigateur. + \end{itemize} + \item \textbf{Recommandations} : + \begin{itemize} + \item \textbf{Ne jamais versionner} l'URL (ex. dans \texttt{.env} ou Git). + \item Utiliser \textbf{HTTPS} (obligatoire). + \item Masquer l'URL dans les logs (ex. via \texttt{redact\_url()} dans + \texttt{pronote-sync}). + \end{itemize} +\end{enumerate} + +\begin{infobox} + \textbf{Source} : {\warningicon\ Recommandation du projet} (inspirée des bonnes pratiques générales + de sécurité). +\end{infobox} + +\section{Intégration dans \texttt{pronote-sync}} + +\begin{itemize} + \item \textbf{Paramètre} : \texttt{PRONOTE\_ICAL\_URL} (ex. \texttt{.env.example} ligne 2). + \item \textbf{Comportement} : + \begin{itemize} + \item Prioritaire en mode \texttt{PRONOTE\_AGENDA\_SOURCE=auto}. + \item Si l'URL est invalide ou expire, repli automatique vers \texttt{pronotepy} (si + \texttt{PRONOTE\_AGENDA\_SOURCE=auto}). + \item \textbf{Aucun repli} si \texttt{PRONOTE\_AGENDA\_SOURCE=ical} (échec explicite). + \end{itemize} +\end{itemize} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ \texttt{pronote\_sync/config/settings.py} + + \texttt{pronote\_sync/sources/ical.py}}. +\end{infobox} + +% ============================================================================= +% FIN DU CHAPITRE +% ============================================================================= diff --git a/docs/ch-method2.tex b/docs/ch-method2.tex new file mode 100644 index 0000000..c0b8f66 --- /dev/null +++ b/docs/ch-method2.tex @@ -0,0 +1,90 @@ +% ============================================================================= +% CHAPITRE : MÉTHODE 2 — CONNEXION DIRECTE +% ============================================================================= + +\chapter{Méthode 2 : Connexion directe (identifiant / mot de passe + ENT)} +\label{ch:method2} + +\section{Principe général} + +Connexion via le protocole propriétaire de Pronote (JSON sur HTTPS), avec +\textbf{chiffrement AES-CBC utilisant une clé dérivée par MD5 (16 octets, soit AES-128)} comme +implémenté dans pronotepy 2.15.7 et mécanisme de défi-réponse. Utilisé par l'interface web. + +\begin{infobox} + \textbf{Statut} : {\emojiinfo\ Observé dans le code local} (délégable à pronotepy via + \texttt{ParentClient} ou \texttt{Client}). +\end{infobox} + +\section{Flux d'authentification} + +\begin{enumerate} + \item \textbf{Initialisation} : Requête GET vers \texttt{/pronote/\{espace\}.html} (ex. + \texttt{parent.html}). + \begin{itemize} + \item Récupère \texttt{h} (ID de session), \texttt{a} (ID espace), \texttt{sCrA}/\texttt{sCoA} + (drapeaux chiffrement/compression). + \end{itemize} + \item \textbf{Échange de clés} : Requête POST vers + \texttt{/pronote/appelfonction/\{a\}/\{h\}/\{numeroOrdre\}}. + \item \textbf{Identification} : Soumission de \texttt{identifiant}, + \texttt{genreConnexion=0}, \texttt{genreEspace=\{a\}}. + \item \textbf{Résolution du défi} : + \begin{itemize} + \item Calcul de \texttt{mtp = MAJUSCULE(HEX(SHA256(alea + mot\_de\_passe)))}. + \item Dérivation de \texttt{key\_challenge = MD5(nom\_utilisateur + mtp)}. + \item Déchiffrement du \texttt{challenge} avec + \textbf{AES-CBC utilisant une clé dérivée par MD5 (16 octets, soit AES-128)}. + \end{itemize} + \item \textbf{Authentification} : Soumission de la réponse au défi. +\end{enumerate} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ Observé dans le code local de \texttt{pronotepy} 2.15.7} (module + \texttt{clients.py} et \texttt{pronoteAPI.py}, vérifié le 2026-09-12). +\end{infobox} + +\section{Intégration dans \texttt{pronote-sync}} + +\begin{itemize} + \item \textbf{Paramètres} : + \begin{itemize} + \item \texttt{PRONOTE\_URL} (ex. \texttt{.env.example} ligne 3). + \item \texttt{PRONOTE\_USERNAME}, \texttt{PRONOTE\_PASSWORD}. + \item \texttt{PRONOTE\_ENT} (slug dans \texttt{\_ENT\_NAMES}). + \item \texttt{PRONOTE\_ACCOUNT\_TYPE} (ex. \texttt{parent}). + \end{itemize} + \item \textbf{Comportement} : + \begin{itemize} + \item Utilise \texttt{pronotepy.ParentClient} pour les comptes parents. + \item \textbf{Repli} : Si iCal échoue en mode \texttt{auto}, \texttt{pronotepy} est utilisé. + \item \textbf{Pas de repli} si \texttt{PRONOTE\_AGENDA\_SOURCE=pronotepy} (échec explicite). + \end{itemize} +\end{itemize} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ \texttt{pronote\_sync/sources/pronote/client.py}} (méthode + \texttt{\_connect\_password}). +\end{infobox} + +\section{ENT supportés} + +Liste \textbf{fermée} des \textbf{30 ENT} résolubles (lignes 52–83 de +\texttt{pronote\_sync/sources/pronote/client.py}) : + +\begin{lstlisting}[language=Python, caption=Liste des ENT supportés, label=lst:ent-list] +_monbureaunumerique, ent_elyco, bordeaux, ent_creuse, occitanie_montpellier, ... +\end{lstlisting} + +\begin{warningbox} + \textbf{Hypothèse à valider} : Les ENT non listés nécessitent une contribution à + \texttt{pronotepy}. +\end{warningbox} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ Code source local de \texttt{pronote-sync}} (2026-09-12). +\end{infobox} + +% ============================================================================= +% FIN DU CHAPITRE +% ============================================================================= diff --git a/docs/ch-method3.tex b/docs/ch-method3.tex new file mode 100644 index 0000000..2c24fdc --- /dev/null +++ b/docs/ch-method3.tex @@ -0,0 +1,212 @@ +% ============================================================================= +% CHAPITRE : MÉTHODE 3 — QR CODE + TOKEN MOBILE +% ============================================================================= + +\chapter{Méthode 3 : QR Code + token mobile (pour \texttt{pronote-sync})} +\label{ch:method3} + +\section{Principe général} + +Mécanisme d'appairage par QR code pour les appareils mobiles, \textbf{contournant +l'authentification ENT/EduConnect}. Le QR code est généré \textbf{depuis l'interface web +Pronote, espace parent \rightarrow paramètres \rightarrow QR code}, puis utilisé avec un +\textbf{PIN à 4 chiffres} pour obtenir un token dont la durée dépend de l'instance/serveur. + +\begin{infobox} + \textbf{Statut} : {\emojicheck\ Pris en charge} par \texttt{pronote-sync} (mode + \texttt{PRONOTE\_AUTH\_MODE=qr\_token}). +\end{infobox} + +\section{Procédure QR pour \texttt{pronote-sync}} +\label{sec:procedure-qr} + +\subsection{Étape 1 : Génération du QR code (interface web)} + +\begin{enumerate} + \item Se connecter à Pronote via un navigateur (espace \textbf{Parent}). + \item Aller dans \textbf{Paramètres \rightarrow Accès mobile / Application mobile}. + \item Définir un \textbf{PIN temporaire à 4 chiffres}. + \item Pronote affiche un \textbf{QR code} contenant un JSON avec les clés : + \begin{itemize} + \item \texttt{login}, \texttt{jeton}, et \texttt{url} (ex. + \texttt{https://[host]/pronote/mobile.parent.html}). + \end{itemize} + \textbf{Le fichier JSON réel contient des identifiants chiffrés et ne doit jamais être + copié, partagé, ou committé.} + \item \textbf{Exporter le QR code} : + \begin{itemize} + \item Sauvegardez le fichier JSON localement ou scannez-le avec un appareil. + \item \textbf{Ne jamais partager} le JSON ou le PIN. + \item \textbf{Le fichier JSON du QR code contient des identifiants chiffrés : ne jamais + le coller dans la documentation ni le committer.} + \end{itemize} +\end{enumerate} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ Observé localement dans l'interface web Pronote} (version non + spécifiée, hypothèse à valider). +\end{infobox} + +\subsection{Étape 2 : Configuration de \texttt{pronote-sync}} + +\begin{enumerate} + \item \textbf{Enregistrer le QR code} : + \begin{itemize} + \item Sauvegarder le JSON dans un fichier (ex. \texttt{/path/to/qr\_code.json}). + \item \textbf{Permissions} : \texttt{chmod 600 /path/to/qr\_code.json}. + \end{itemize} + \item \textbf{Configurer \texttt{.env}} : + \begin{lstlisting}[language=bash, caption=Configuration QR Code dans .env, label=lst:qr-env] +PRONOTE_AUTH_MODE=qr_token +PRONOTE_QR_CODE_FILE=/path/to/qr_code.json +PRONOTE_QR_PIN= # renseigner localement la valeur secrète du PIN (jamais committée) + \end{lstlisting} + \textbf{Note} : \texttt{.env.example} ne doit \textbf{jamais} contenir de PIN concret. +\end{enumerate} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ Observé dans \texttt{.env.example}} (lignes 21–25) et + \texttt{pronote\_sync/sources/pronote/client.py}. +\end{infobox} + +\subsection{Étape 3 : Premier login (enrôlement)} + +\begin{enumerate} + \item \texttt{pronote-sync} lit \texttt{PRONOTE\_QR\_CODE\_FILE} et \texttt{PRONOTE\_QR\_PIN}. + \item Appel à \texttt{pronotepy.ParentClient.qrcode\_login(qr\_code, pin, uuid)} : + \begin{itemize} + \item \texttt{qr\_code} : JSON du fichier QR. + \item \texttt{pin} : PIN à 4 chiffres. + \item \texttt{uuid} : UUID permanent généré par \texttt{pronote-sync} (ex. + \texttt{pronote-sync-\{uuid4()\}}). + \end{itemize} + \item \textbf{Déchiffrement} : + \begin{itemize} + \item Algorithme : + \textbf{AES-CBC utilisant une clé dérivée par MD5 (16 octets, soit AES-128)}. + \item Clé : \texttt{MD5(PIN)} (dérivée du PIN secret). + \item IV : 16 octets nuls. + \item Résultat : \texttt{login} et \texttt{jeton} en clair. + \end{itemize} + \item \textbf{Échange de token} : Pronote retourne un \texttt{jetonConnexionAppliMobile} (token + dont la durée dépend de l'instance/serveur). + \item \textbf{Persistance} : \texttt{pronote-sync} sauvegarde les credentials via + \texttt{export\_credentials()} dans \texttt{.pronote\_auth\_state.json} (mode \texttt{0600}). +\end{enumerate} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ Observé dans le code local de \texttt{pronotepy} 2.15.7} + (\texttt{clients.py} lignes 181–189) + \texttt{pronote\_sync/sources/pronote/client.py} (méthode + \texttt{\_enroll\_qr\_code}). +\end{infobox} + +\subsection{Étape 4 : Connexions ultérieures (auto-login)} + +\begin{enumerate} + \item \texttt{pronote-sync} charge \texttt{.pronote\_auth\_state.json}. + \item Appel à \texttt{pronotepy.ParentClient.token\_login(**credentials)} : + \begin{itemize} + \item \texttt{pronote\_url}, \texttt{username}, \texttt{password} (token), \texttt{uuid}. + \end{itemize} + \item \textbf{Rotation du token} : Le token est \textbf{remplacé uniquement si le serveur + renvoie \texttt{jetonConnexionAppliMobile}} (observé dans \texttt{pronotepy} 2.15.7, + \texttt{clients.py:382–387}). + \item \textbf{Persistance} : Les credentials sont sauvegardés dans + \texttt{.pronote\_auth\_state.json} après chaque opération réussie. +\end{enumerate} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ Observé dans le code local de \texttt{pronotepy} 2.15.7} + (\texttt{clients.py} lignes 245–280) + \texttt{pronote\_sync/sources/pronote/client.py} (méthode + \texttt{\_connect\_qr\_token}). +\end{infobox} + +\section{Cycle de vie des tokens} + +\begin{itemize} + \item \textbf{QR code} : Valide \textbf{~10 minutes} après génération + ({\warningicon\ \textbf{Hypothèse à valider}} : cette durée n'est attestée que par un + message d'exception dans \texttt{pronotepy} et n'est pas une garantie officielle/indépendante + de l'instance). + \item \textbf{\texttt{jetonConnexionAppliMobile}} : + \begin{itemize} + \item Durée \textbf{dépendante de l'instance/serveur} (observation du 2026-09-12, + hypothèse : peut persister jusqu'à la fin de l'année scolaire, non garanti). + \item \textbf{Remplacé uniquement si le serveur renvoie + \texttt{jetonConnexionAppliMobile}} (observé dans \texttt{pronotepy} 2.15.7, + \texttt{clients.py:382–387}). + \item \textbf{Révocable} manuellement dans Pronote (Paramètres \rightarrow Accès mobile). + \end{itemize} +\end{itemize} + +\begin{infobox} + \textbf{Source} : {\warningicon\ Comportement variable selon les instances} (à tester localement). +\end{infobox} + +\section{Sécurité} + +\begin{enumerate} + \item \textbf{Fichiers sensibles} : + \begin{itemize} + \item \texttt{.pronote\_auth\_state.json} : \textbf{Ne jamais versionner} (couvert par + \texttt{.gitignore}). + \item \texttt{PRONOTE\_QR\_CODE\_FILE} : \textbf{Ne jamais committer} (ex. dans Git). + \end{itemize} + \item \textbf{Secrets} : + \begin{itemize} + \item Le PIN et le contenu du QR code sont \textbf{masqués} dans les logs (via + \texttt{redact\_secrets()}). + \item Les exceptions sont \textbf{expurgées} (via \texttt{redact\_exception()}). + \end{itemize} + \item \textbf{Recommandations} : + \begin{itemize} + \item Utiliser un \textbf{PIN robuste} (éviter les codes simples comme \guillemotleft 0000 \guillemotright ou + des séquences évidentes). + \item \textbf{Révoquer} le token en cas de compromission (via Pronote web). + \end{itemize} +\end{enumerate} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ \texttt{pronote\_sync/utils/redaction.py} + + \texttt{pronote\_sync/sources/pronote/client.py}} (méthode \texttt{\_collect\_auth\_secrets}). +\end{infobox} + +\section{Erreurs et repli} + +\begin{itemize} + \item \textbf{\texttt{PronoteAuthRotationError}} : Levée si : + \begin{itemize} + \item Le token persisté est \textbf{invalide/expiré}. + \item Le fichier QR ou le PIN est \textbf{manquant/invalide}. + \end{itemize} + \item \textbf{Action requise} : + \begin{enumerate} + \item Supprimer \texttt{.pronote\_auth\_state.json}. + \item Générer un \textbf{nouveau QR code depuis l'interface web Pronote, espace parent}. + \item Relancer \texttt{pronote-sync}. + \end{enumerate} +\end{itemize} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ Observé dans \texttt{pronote\_sync/errors.py} + + \texttt{pronote\_sync/sources/pronote/client.py}} (lignes 346–364). +\end{infobox} + +\section{Incompatibilités} + +\begin{itemize} + \item \textbf{Mode \texttt{dry-run}} : \textbf{Incompatible} avec + \texttt{PRONOTE\_AUTH\_MODE=qr\_token} (risque de désynchronisation du token local). + \begin{itemize} + \item \texttt{pronote-sync --dry-run} \textbf{refuse} le mode \texttt{qr\_token} avant toute + connexion. + \end{itemize} +\end{itemize} + +\begin{infobox} + \textbf{Source} : {\emojiinfo\ \texttt{docs/exploitation.md}} (ligne 65–66). +\end{infobox} + +% ============================================================================= +% FIN DU CHAPITRE +% ============================================================================= diff --git a/docs/ch-method4.tex b/docs/ch-method4.tex new file mode 100644 index 0000000..de6356f --- /dev/null +++ b/docs/ch-method4.tex @@ -0,0 +1,17 @@ +% ============================================================================= +% CHAPITRE : MÉTHODE 4 — SSO ENT (CAS/SAML) +% ============================================================================= + +\chapter{Méthode 4 : SSO ENT (CAS/SAML)} +\label{ch:method4} + +\begin{warningbox} + \textbf{Statut} : {\emojicross\ Non implémenté} dans \texttt{pronote-sync}. + + Seuls les 30 ENT de la liste fermée \texttt{\_ENT\_NAMES} (pronotepy 2.15.7) sont supportés via + \texttt{ent} dans \texttt{ParentClient}. \textbf{Pas de SSO générique CAS/SAML.} +\end{warningbox} + +% ============================================================================= +% FIN DU CHAPITRE +% ============================================================================= diff --git a/docs/ch-method5.tex b/docs/ch-method5.tex new file mode 100644 index 0000000..ee0b10e --- /dev/null +++ b/docs/ch-method5.tex @@ -0,0 +1,16 @@ +% ============================================================================= +% CHAPITRE : MÉTHODE 5 — EDUCONNECT (HUBEDUCONNECT) +% ============================================================================= + +\chapter{Méthode 5 : EduConnect (HubEduConnect)} +\label{ch:method5} + +\begin{warningbox} + \textbf{Statut} : {\emojicross\ Non implémenté} dans \texttt{pronote-sync}. + + Nécessite une intégration CAS/SAML générique, \textbf{non supportée par ce projet}. +\end{warningbox} + +% ============================================================================= +% FIN DU CHAPITRE +% ============================================================================= diff --git a/docs/ch-method6.tex b/docs/ch-method6.tex new file mode 100644 index 0000000..a781d82 --- /dev/null +++ b/docs/ch-method6.tex @@ -0,0 +1,16 @@ +% ============================================================================= +% CHAPITRE : MÉTHODE 6 — CAS DIRECT +% ============================================================================= + +\chapter{Méthode 6 : CAS direct} +\label{ch:method6} + +\begin{warningbox} + \textbf{Statut} : {\emojicross\ Non implémenté} dans \texttt{pronote-sync}. + + Non supporté. +\end{warningbox} + +% ============================================================================= +% FIN DU CHAPITRE +% ============================================================================= diff --git a/docs/ch-method7.tex b/docs/ch-method7.tex new file mode 100644 index 0000000..73030b4 --- /dev/null +++ b/docs/ch-method7.tex @@ -0,0 +1,17 @@ +% ============================================================================= +% CHAPITRE : MÉTHODE 7 — API PUBLIQUE +% ============================================================================= + +\chapter{Méthode 7 : API publique} +\label{ch:method7} + +\begin{warningbox} + \textbf{Statut} : {\emojicross\ Inexistante}. + + Aucune API publique n'est utilisée/implémentée par ce projet ; aucune API officielle + publique n'a été vérifiée à la date du 2026-09-12. +\end{warningbox} + +% ============================================================================= +% FIN DU CHAPITRE +% ============================================================================= diff --git a/docs/ch-overview.tex b/docs/ch-overview.tex new file mode 100644 index 0000000..751b7bc --- /dev/null +++ b/docs/ch-overview.tex @@ -0,0 +1,38 @@ +% ============================================================================= +% CHAPITRE : TABLEAU DE COMPATIBILITÉ +% ============================================================================= + +\chapter{Tableau de compatibilité avec \texttt{pronote-sync}} +\label{ch:overview} + +\begin{table}[htbp] + \centering + \caption{Méthodes d'authentification et leur statut dans \texttt{pronote-sync}} + \label{tab:compatibilite} + \begin{tabularx}{\textwidth}{L{2.5cm} L{3cm} L{3cm} L{2.5cm} L{4cm}} + \toprule + \textbf{Méthode} & \textbf{Statut dans \texttt{pronote-sync}} & \textbf{Implémentation} & \textbf{Source} & \textbf{Notes} \\ + \midrule + + + \textbf{URL iCal sécurisée} (\texttt{icalsecurise}) & \emojicheck\ Pris en charge & Source \texttt{ical} (prioritaire en mode \texttt{auto}) & \emojiinfo\ \texttt{pronote\_sync/sources/ical.py} & Jeton dans l'URL traité comme secret. \\ + + \textbf{Connexion directe} (mot de passe + ENT) & \emojicheck\ Pris en charge & Source \texttt{pronotepy} (repli si iCal échoue) & \emojiinfo\ \texttt{pronote\_sync/sources/pronote/client.py} & Liste fermée \texttt{\_ENT\_NAMES} (lignes 52–84). \\ + + \textbf{QR Code + token mobile} & \emojicheck\ Pris en charge & Mode \texttt{PRONOTE\_AUTH\_MODE=qr\_token} & \emojiinfo\ \texttt{pronotepy.Client.qrcode\_login} + \texttt{token\_login} & Voir \hyperref[sec:procedure-qr]{Procédure QR} (Section \ref{sec:procedure-qr}). \\ + + \textbf{SSO ENT (CAS/SAML)} & \emojicross\ Non implémenté & — & — & Seuls les 30 ENT de la liste fermée \texttt{\_ENT\_NAMES} (pronotepy 2.15.7) sont supportés via \texttt{ent} dans \texttt{ParentClient}. \textbf{Pas de SSO générique CAS/SAML.} \\ + + \textbf{EduConnect (HubEduConnect)} & \emojicross\ Non implémenté & — & — & Nécessite une intégration CAS/SAML générique, \textbf{non supportée par ce projet}. \\ + + \textbf{CAS direct} & \emojicross\ Non implémenté & — & — & Non supporté. \\ + + \textbf{API publique} & \emojicross\ Inexistante & — & — & Aucune API publique n'est utilisée/implémentée par ce projet ; aucune API officielle publique n'a été vérifiée à la date du 2026-09-12. \\ + + \bottomrule + \end{tabularx} +\end{table} + +% ============================================================================= +% FIN DU CHAPITRE +% ============================================================================= diff --git a/docs/frontmatter.tex b/docs/frontmatter.tex new file mode 100644 index 0000000..f5dd633 --- /dev/null +++ b/docs/frontmatter.tex @@ -0,0 +1,100 @@ +% ============================================================================= +% PAGE DE TITRE — Authentification Pronote +% ============================================================================= + +\begin{titlepage} + \newgeometry{margin=2cm} + \begin{center} + \vspace*{2cm} + + {\Huge\bfseries\color{primaryNavy} Authentification Pronote\\} + {\huge\bfseries\color{secondarySlate} Référence technique pour \texttt{pronote-sync}} + + \vspace{1.5cm} + + {\Large\color{secondarySlate} Version 1.0 — 12 septembre 2026} + + \vspace{2cm} + + {\large\color{gray} Équipe Architecture et Sécurité} + + \vspace{1cm} + + {\small\color{gray} + Ce document n'est pas un guide officiel. Il n'est ni approuvé, ni validé, ni autorisé + par le Ministère de l'Éducation Nationale française ni par Docaposte (éditeur de + Pronote / Index Éducation). + } + + \vspace{2cm} + + \begin{warningbox} + \centering + {\bfseries\large\color{warningRed} AVERTISSEMENT}\\ + \vspace{0.5cm} + {\small + Ce document repose sur des observations directes du code source de + \texttt{pronotepy} (version 2.15.7, vérifiée localement le 2026-09-12), des issues + publiques du dépôt \texttt{bain3/pronotepy}, et des tests d'intégration du projet + \texttt{pronote-sync}.\\ + + {\bfseries Un essai réel sur l'instance Pronote cible est nécessaire avant tout usage + en production. Les tests/mocks ne prouvent pas la compatibilité d'instance.} + } + \end{warningbox} + + \vfill + + {\small\color{gray} Compilé avec LuaLaTeX} + + \end{center} + \restoregeometry +\end{titlepage} + +% ============================================================================= +% TABLE DES MATIÈRES +% ============================================================================= + +\newpage +\tableofcontents +\thispagestyle{fancy} + +% ============================================================================= +% LISTE DES TABLEAUX (optionnel) +% ============================================================================= + +\newpage +\listoftables +\thispagestyle{fancy} + +% ============================================================================= +% AVERTISSEMENT INITIAL +% ============================================================================= + +\newpage +\section*{Avertissement initial} +\addcontentsline{toc}{section}{Avertissement initial} + +\begin{infobox} + \textbf{Convention de qualification} : + + \begin{itemize} + \item {\emojiinfo\ \textbf{Observé dans le code local}} : Mécanisme vérifié dans le code + source de \texttt{pronotepy} 2.15.7 ou \texttt{pronote-sync}. + \item {\emojiinfo\ \textbf{Observé localement}} : Comportement constaté dans les interfaces + Pronote (version non spécifiée, hypothèse à valider). + \item {\warningicon\ \textbf{Hypothèse à valider}} : Affirmation non vérifiée, nécessitant + une confirmation par test sur une instance réelle. + \end{itemize} +\end{infobox} + +\vspace{1cm} + +\begin{warningbox} + \textbf{Note importante (2026-09-12)} : + + Un essai réel sur l'instance Pronote cible est nécessaire avant tout usage en production. + Les tests/mocks ne prouvent pas la compatibilité d'instance. +\end{warningbox} + +\newpage diff --git a/docs/glossaire.tex b/docs/glossaire.tex new file mode 100644 index 0000000..98d7cd9 --- /dev/null +++ b/docs/glossaire.tex @@ -0,0 +1,28 @@ +% ============================================================================= +% GLOSSAIRE (chapitre non numéroté) +% ============================================================================= + +\chapter*{Glossaire} +\addcontentsline{toc}{chapter}{Glossaire} + +\begin{tabularx}{\textwidth}{L{4cm} L{12cm}} + \toprule + \textbf{Terme} & \textbf{Définition} \\ + \midrule + + \textbf{ENT} & Espace Numérique de Travail (ex. Mon Bureau Numérique, Paris Classe Numérique). \\ + + \textbf{Jeton \texttt{icalsecurise}} & Token secret intégré dans l'URL iCal, équivalent à un mot de passe. \\ + + \textbf{\texttt{jetonConnexionAppliMobile}} & Token obtenu après appairage QR code, dont la durée dépend de l'instance/du serveur et n'est pas garantie. \\ + + \textbf{UUID} & Identifiant unique permanent pour l'application (ex. \texttt{pronote-sync-\{uuid4()\}}). \\ + + \textbf{PIN} & Code à 4 chiffres défini lors de la génération du QR code. \\ + + \bottomrule +\end{tabularx} + +% ============================================================================= +% FIN DU GLOSSAIRE +% ============================================================================= diff --git a/docs/historique.tex b/docs/historique.tex new file mode 100644 index 0000000..abbde81 --- /dev/null +++ b/docs/historique.tex @@ -0,0 +1,24 @@ +% ============================================================================= +% HISTORIQUE DES RÉVISIONS (chapitre non numéroté) +% ============================================================================= + +\chapter*{Historique des révisions} +\addcontentsline{toc}{chapter}{Historique des révisions} + +\begin{tabularx}{\textwidth}{L{2.4cm} L{2.6cm} L{11cm}} + \toprule + \textbf{Date} & \textbf{Auteur} & \textbf{Modifications} \\ + \midrule + + 2026-09-12 & Agent tech-writer & Refonte complète : qualification des affirmations, ajout des sources, tableau de compatibilité, procédure QR alignée sur pronotepy 2.15.7. \\ + + 2026-09-12 & Agent tech-writer & Corrections suite à revue indépendante (ticket \#10) : précision cryptographie (AES-128), qualification des sources, alignement nombre d'ENT (30), clarification SSO/CAS, exemples non copiables, note d'essai réel. \\ + + 2026-09-12 & Agent tech-writer & Corrections suite à revue ticket \#10 : suppression de tous les placeholders de secrets remplacés par de la prose descriptive ; clarification du périmètre réel des méthodes d'authentification (accès limité aux opérations implémentées) ; qualification de la durée du token \texttt{jetonConnexionAppliMobile} comme dépendante de l'instance/serveur et non garantie. \\ + + \bottomrule +\end{tabularx} + +% ============================================================================= +% FIN DE L'HISTORIQUE +% ============================================================================= diff --git a/docs/preamble.tex b/docs/preamble.tex new file mode 100644 index 0000000..8da048e --- /dev/null +++ b/docs/preamble.tex @@ -0,0 +1,159 @@ +% ============================================================================= +% PRÉAMBULE LaTeX — Authentification Pronote +% ============================================================================= + +% --- Classe de document --- +\documentclass[11pt,a4paper,oneside]{report} + +% --- Encodage et langue --- +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[french]{babel} +\usepackage{lmodern} + +% --- Polices (plan documentaire : EB Garamond / Carlito / DejaVu Sans Mono) --- +% EB Garamond (sérif) : police principale du document +\usepackage{ebgaramond} +% Carlito (sans-sérif, compatible métriquement Calibri) +\usepackage[sfdefault]{carlito} +% DejaVu Sans Mono (chasse fixe) : code, JSON, requêtes HTTP +% (fontspec est déjà chargé par EB Garamond sous LuaLaTeX) +\setmonofont{DejaVu Sans Mono}[Scale=0.9] + +% --- Couleurs (palette Bleu Institutionnel & Ardoise) --- +\usepackage{xcolor} +\definecolor{primaryNavy}{RGB}{20,45,85} +\definecolor{secondarySlate}{RGB}{70,95,125} +\definecolor{accentSteel}{RGB}{0,115,150} +\definecolor{lightGray}{RGB}{240,240,240} +\definecolor{warningRed}{RGB}{180,50,50} + +% --- Mise en page --- +\usepackage[a4paper, margin=2.5cm, top=2cm, bottom=2cm]{geometry} +\usepackage{parskip} +\setlength{\parskip}{1em} +\setlength{\parindent}{0pt} + +% --- Hyperliens et PDF --- +\usepackage{hyperref} +\hypersetup{ + colorlinks=true, + linkcolor=accentSteel, + urlcolor=accentSteel, + citecolor=secondarySlate, + filecolor=primaryNavy, + menucolor=primaryNavy, + runcolor=primaryNavy, + pdfauthor={Équipe Architecture & Sécurité}, + pdftitle={Authentification Pronote — Référence technique}, + pdfsubject={Référence technique d'authentification pour pronote-sync}, + pdfkeywords={Pronote, authentification, pronote-sync, QR code, token, ENT, iCal}, + bookmarksopen=true, + bookmarksnumbered=true +} + +% --- Titres et sections --- +\usepackage{titlesec} +\titleformat{\chapter}[display] + {\normalfont\huge\bfseries\color{primaryNavy}} + {\chaptertitlename\ \thechapter} + {20pt} + {\Huge\color{primaryNavy}} +\titleformat{\section} + {\normalfont\Large\bfseries\color{primaryNavy}} + {\thesection} + {1em} + {\color{primaryNavy}} +\titleformat{\subsection} + {\normalfont\large\bfseries\color{secondarySlate}} + {\thesubsection} + {1em} + {\color{secondarySlate}} +\titleformat{\subsubsection} + {\normalfont\bfseries\color{secondarySlate}} + {\thesubsubsection} + {1em} + {\color{secondarySlate}} + +% --- Tableaux --- +\usepackage{tabularx} +\usepackage{booktabs} +\usepackage{array} +\newcolumntype{L}[1]{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}\hspace{1em}}p{#1}} +\newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}\hspace{1em}}p{#1}} +\newcolumntype{R}[1]{>{\raggedleft\let\newline\\\arraybackslash\hspace{0pt}\hspace{1em}}p{#1}} + +% --- Listes et encadrés --- +\usepackage{enumitem} +\setlist[itemize]{leftmargin=*, topsep=0.5em, itemsep=0.25em} +\setlist[enumerate]{leftmargin=*, topsep=0.5em, itemsep=0.25em} + +% --- Callouts (encadrés colorés) --- +\usepackage{mdframed} +\newmdenv[linecolor=warningRed, linewidth=2pt, leftmargin=10pt, rightmargin=10pt, innerleftmargin=10pt, innerrightmargin=10pt, backgroundcolor=red!5!white, roundcorner=5pt, skipabove=10pt, skipbelow=10pt]{warningbox} +\newmdenv[linecolor=secondarySlate, linewidth=2pt, leftmargin=10pt, rightmargin=10pt, innerleftmargin=10pt, innerrightmargin=10pt, backgroundcolor=blue!5!white, roundcorner=5pt, skipabove=10pt, skipbelow=10pt]{infobox} + +% --- Code source --- +\usepackage{listings} +\lstdefinestyle{pronote}{ + basicstyle=\ttfamily\footnotesize, + breaklines=true, + frame=single, + rulecolor=\color{gray!30}, + backgroundcolor=\color{lightGray}, + keywordstyle=\color{primaryNavy}, + stringstyle=\color{secondarySlate}, + commentstyle=\color{gray}, + showstringspaces=false, + tabsize=2, + captionpos=b, + xleftmargin=10pt, + xrightmargin=10pt, + aboveskip=10pt, + belowskip=10pt +} +\lstset{style=pronote} + +% --- Symboles et icônes --- +\usepackage{amssymb} +\usepackage{pifont} +\newcommand{\checkmarkicon}{\ding{51}} % ✓ +\newcommand{\warningicon}{\ding{43}} % ⚠ +\newcommand{\infoicon}{\ding{48}} % ℹ +\newcommand{\crossicon}{\ding{55}} % ✗ + +% --- Mathématiques --- +\usepackage{amsmath} + +% --- Table des matières --- +\usepackage{tocloft} +\renewcommand{\cftchapfont}{\normalfont\bfseries\color{primaryNavy}} +\renewcommand{\cftsecfont}{\normalfont\color{primaryNavy}} +\renewcommand{\cftsubsecfont}{\normalfont\color{secondarySlate}} + +% --- En-têtes et pieds de page --- +\usepackage{fancyhdr} +\pagestyle{fancy} +\fancyhf{} +\fancyhead[LE,RO]{\thepage} +\fancyhead[LO]{\nouppercase{\rightmark}} +\fancyhead[RE]{\nouppercase{\leftmark}} +\renewcommand{\headrulewidth}{0.5pt} +\renewcommand{\footrulewidth}{0pt} + +% --- Espacement vertical --- +\usepackage{setspace} +\onehalfspacing + +% --- Césure --- +\usepackage{microtype} + +% --- Support des emojis (repli sur texte si non disponible) --- +\newcommand{\emojiwarning}{\warningicon} +\newcommand{\emojicheck}{\checkmarkicon} +\newcommand{\emojicross}{\crossicon} +\newcommand{\emojiinfo}{\infoicon} + +% ============================================================================= +% FIN DU PRÉAMBULE +% ============================================================================= diff --git a/docs/pronote-auth.pdf b/docs/pronote-auth.pdf index 6fd2ac7..cba610f 100644 Binary files a/docs/pronote-auth.pdf and b/docs/pronote-auth.pdf differ diff --git a/docs/pronote-auth.tex b/docs/pronote-auth.tex index 8e91424..a13a1a5 100644 --- a/docs/pronote-auth.tex +++ b/docs/pronote-auth.tex @@ -9,8 +9,8 @@ %% %% INSTRUCTIONS DE COMPILATION : %% Ce document est conçu pour être compilé avec LuaLaTeX : -%% lualatex -interaction=nonstopmode docs/pronote-auth.tex -%% lualatex -interaction=nonstopmode docs/pronote-auth.tex +%% TEXINPUTS="docs:" lualatex -interaction=nonstopmode -output-directory=docs docs/pronote-auth.tex +%% TEXINPUTS="docs:" lualatex -interaction=nonstopmode -output-directory=docs docs/pronote-auth.tex %% (Deux passes nécessaires pour la génération de la table des matières, %% des références croisées et des hyperliens). %% @@ -52,5 +52,9 @@ \include{annex-libraries} \include{annex-comparison} +\include{annex-ecarts} + +\include{glossaire} +\include{historique} \end{document}