fix(config): durcir le contrat ExternalEndpoint (file://, matrice de tests, doc) #63

Open
opened 2026-09-13 12:40:27 +02:00 by OpenCode · 0 comments
Collaborator

Contexte

Corrections issues de la revue indépendante des PR #59/#60/#61 (ticket #16, centralisation du contrat des endpoints externes).

Constat bloquant : le schéma file:// est accepté par la configuration de production (Pronote iCal, Blog RSS) alors qu'aucun client ne le consomme réellement. BlogRSSClient.fetch_and_parse appelle inconditionnellement requests.get() (pronote_sync/sources/blog/rss.py), donc un BLOG_ENDPOINT__URL=file://… passe la validation puis dégrade silencieusement. Les tests ne le détectent pas car ils mockent requests.get avec une URL file:// factice. Cela contrevient au critère du ticket #16 : « conserver la possibilité de tests locaux injectés sans transformer ces facilités de test en comportement implicite de production ».

Constats complémentaires : matrice de tests de contrat incomplète ; hide_input_in_errors absent de PronoteSettings/CalDAVSettings/BlogSettings ; README.LLM.md documente encore les anciens noms de variables.

Périmètre (liste fermée)

P0 — bloquant

  1. Retirer le schéma file du contrat ExternalEndpoint pour les trois connecteurs (CalDAV, Pronote iCal, Blog RSS). Seuls https (et http en loopback explicite via allow_insecure_http) restent acceptés. Aucune lecture de fichier local n'est ajoutée en production.
  2. Réécrire les fixtures de test qui utilisent file:// (Blog RSS, test_fallback.py) avec une URL https:// factice interceptée par mock HTTP (responses), sans accès réseau.
  3. Ajouter hide_input_in_errors=True aux SettingsConfigDict de PronoteSettings, CalDAVSettings, BlogSettings (parité avec XmppSettings et ExternalEndpoint).
  4. Matrice de tests paramétrée exhaustive du contrat, partagée par les trois connecteurs : précédence canonique/alias avec DeprecationWarning, loopback HTTP accepté/refusé selon allow_insecure_http, extra='forbid', frozen=True, userinfo rejeté, query params sensibles rejetés/expurgés, file:// rejeté.

P1 — documentation
5. README.LLM.md : retirer BLOG_RSS_URL, PRONOTE_URL, PRONOTE_ICAL_URL, CALDAV_URL et documenter le schéma *_ENDPOINT__URL + statut des alias dépréciés.
6. Aligner .env.example, GUIDE_DEV_PYTHON.md et docs/pronote-auth.md sur le même contrat.

Hors périmètre

  • Toute évolution du protocole des connecteurs (parsing métier, format iCal/RSS, logique de fallback).
  • Mécanisme de lecture de fichier local en production.
  • Modification de l'endpoint XMPP.
  • Modification des correctifs sécurité #53/#54/#58 déjà dans main (seule leur préservation est requise).

Critères d'acceptation

  • Aucune configuration de production n'accepte file:// (les trois connecteurs).
  • rg 'file://' tests/ ne retourne plus de dépendance à ce schéma.
  • La matrice de tests de contrat est paramétrée et couvre les cas listés au point 4.
  • README.LLM.md et les guides ne contredisent plus le contrat unique.
  • pytest --cov, ruff check ., mypy ., bandit -r pronote_sync/ passent sur la branche.

Références

## Contexte Corrections issues de la revue indépendante des PR #59/#60/#61 (ticket #16, centralisation du contrat des endpoints externes). Constat bloquant : le schéma `file://` est accepté par la configuration de production (Pronote iCal, Blog RSS) alors qu'aucun client ne le consomme réellement. `BlogRSSClient.fetch_and_parse` appelle inconditionnellement `requests.get()` (`pronote_sync/sources/blog/rss.py`), donc un `BLOG_ENDPOINT__URL=file://…` passe la validation puis dégrade silencieusement. Les tests ne le détectent pas car ils mockent `requests.get` avec une URL `file://` factice. Cela contrevient au critère du ticket #16 : « conserver la possibilité de tests locaux injectés sans transformer ces facilités de test en comportement implicite de production ». Constats complémentaires : matrice de tests de contrat incomplète ; `hide_input_in_errors` absent de `PronoteSettings`/`CalDAVSettings`/`BlogSettings` ; `README.LLM.md` documente encore les anciens noms de variables. ## Périmètre (liste fermée) **P0 — bloquant** 1. Retirer le schéma `file` du contrat `ExternalEndpoint` pour les trois connecteurs (CalDAV, Pronote iCal, Blog RSS). Seuls `https` (et `http` en loopback explicite via `allow_insecure_http`) restent acceptés. Aucune lecture de fichier local n'est ajoutée en production. 2. Réécrire les fixtures de test qui utilisent `file://` (Blog RSS, `test_fallback.py`) avec une URL `https://` factice interceptée par mock HTTP (`responses`), sans accès réseau. 3. Ajouter `hide_input_in_errors=True` aux `SettingsConfigDict` de `PronoteSettings`, `CalDAVSettings`, `BlogSettings` (parité avec `XmppSettings` et `ExternalEndpoint`). 4. Matrice de tests paramétrée exhaustive du contrat, partagée par les trois connecteurs : précédence canonique/alias avec `DeprecationWarning`, loopback HTTP accepté/refusé selon `allow_insecure_http`, `extra='forbid'`, `frozen=True`, userinfo rejeté, query params sensibles rejetés/expurgés, `file://` rejeté. **P1 — documentation** 5. `README.LLM.md` : retirer `BLOG_RSS_URL`, `PRONOTE_URL`, `PRONOTE_ICAL_URL`, `CALDAV_URL` et documenter le schéma `*_ENDPOINT__URL` + statut des alias dépréciés. 6. Aligner `.env.example`, `GUIDE_DEV_PYTHON.md` et `docs/pronote-auth.md` sur le même contrat. ## Hors périmètre - Toute évolution du protocole des connecteurs (parsing métier, format iCal/RSS, logique de fallback). - Mécanisme de lecture de fichier local en production. - Modification de l'endpoint XMPP. - Modification des correctifs sécurité #53/#54/#58 déjà dans `main` (seule leur préservation est requise). ## Critères d'acceptation - Aucune configuration de production n'accepte `file://` (les trois connecteurs). - `rg 'file://' tests/` ne retourne plus de dépendance à ce schéma. - La matrice de tests de contrat est paramétrée et couvre les cas listés au point 4. - `README.LLM.md` et les guides ne contredisent plus le contrat unique. - `pytest --cov`, `ruff check .`, `mypy .`, `bandit -r pronote_sync/` passent sur la branche. ## Références - Ticket parent : #16 - PR concernées : #59, #60, #61
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: AntoineVe/college-infos#63