Aller au contenu

ADR-030 : Injection de routes par commande explicite et règle 4.3

Statut

Acceptée, Forge 1.0.0-beta.17 (ticket GOV-ADR-STATUS-RESOLVE-001).
Proposé en 1.0.0-beta.15 (ticket ADR-EXPLICIT-ROUTE-INJECTION-001), révisé en 1.0.0-beta.17 (ticket ADR-030-REVISION-001) pour retirer la référence à starter:build, commande supprimée par l'ADR-035.

La décision est appliquée dans le code : les make:public-* injectent les routes selon les quatre conditions, avec détection robuste du marqueur router (FIX-PUBLIC-ROUTES-MARKER-001).
La précision du texte de la règle 4.3 de CHARTE_DOC.md reste un geste mainteneur distinct, non appliqué par cet ADR.

Précise la portée de la règle de génération 4.3 de la charte v2 (« le fichier principal de routes applicatives mvc/routes.py reste sous le contrôle explicite du développeur ; pas de marqueurs commentaires auto-injectés, pas de réécriture automatique »).
Aucune modification de CHARTE_DOC.md n'est appliquée tant que le mainteneur n'a pas validé cet ADR.


Date

2026-06-08 (révisé le 2026-06-19).


Contexte

La règle 4.3 de la charte v2 interdit la réécriture automatique de mvc/routes.py.
Or les commandes make:public-* l'écrivent aujourd'hui :

  • forge make:public-page, make:public-list, make:public-form, make:public-show et make:public-contact insèrent un import et un bloc de route dans le mvc/routes.py existant (cli/public/public_page.py, public_list.py, public_form.py, etc.).

Note historique : un second injecteur, forge starter:build, encadrait son bloc par des marqueurs # forge-starter:<nom>:start / :end et ajustait la route racine.
Cette commande a été supprimée par l'ADR-035 (bêta.16, retrait de la génération de starters).
Le présent ADR ne couvre donc plus que les make:public-*.

Cette injection est un choix délibéré, jamais réconcilié avec la lettre de la règle 4.3.
Un auditeur strict peut donc considérer le comportement livré comme non conforme à une règle marquée « non négociable ».

Dans le même temps, le générateur make:crud n'injecte pas : il affiche le bloc de routes sur la sortie standard, à coller manuellement.
Il existe donc deux comportements selon le générateur.

Le point à trancher : la règle 4.3 interdit-elle toute écriture dans mvc/routes.py, ou seulement l'écriture silencieuse et automatique que le développeur n'a pas demandée ?


Décision

La règle 4.3 vise l'écriture silencieuse et automatique : Forge ne doit jamais réécrire mvc/routes.py de sa propre initiative, en arrière-plan, sans geste de l'utilisateur.
Elle n'interdit pas une commande de scaffolding que le développeur invoque explicitement.

Une commande Forge est autorisée à injecter des routes dans mvc/routes.py si, et seulement si, les quatre conditions suivantes sont réunies :

  1. Explicite : l'écriture résulte d'une commande que l'utilisateur tape lui-même (make:public-*).
    Aucune écriture déclenchée par un autre flux (démarrage, autre générateur, hook) n'est permise.
  2. Idempotente : ré-exécuter la commande ne duplique pas le bloc ; la présence du bloc (ou de la route) est détectée avant insertion.
  3. Délimitée et visible : le bloc injecté est clairement identifiable, de sorte que le développeur voie et puisse retirer ce qui a été ajouté.
  4. Annoncée : la commande signale sur la sortie standard ce qu'elle a écrit (fichier touché, route ajoutée).

Toute détection de point d'injection se fait de manière robuste (analyse AST ou ancrage fiable), jamais par simple sous-chaîne susceptible d'être trompée par un commentaire ou une chaîne (cf. correctif FIX-PUBLIC-ROUTES-MARKER-001).

Le mode affichage de make:crud reste une variante conservatrice acceptable et n'a pas à être aligné sur l'injection : pour un générateur d'entité unique, laisser le développeur coller lui-même la route est un choix légitime.
Les deux modes coexistent, chacun adapté à son contexte (scaffolding d'une page publique vs route d'une entité).


Conséquences

  • La charte (règle 4.3) sera précisée, après validation du mainteneur, pour distinguer « réécriture silencieuse/automatique » (interdite) de « injection par commande explicite répondant aux quatre conditions » (autorisée).
  • Les make:public-* sont conformes dès lors qu'ils respectent les quatre conditions ; le correctif de détection robuste du marqueur router (FIX-PUBLIC-ROUTES-MARKER-001) renforce la condition 2.
  • Les contrôleurs applicatifs (mvc/controllers/*.py) ne sont pas couverts par cette autorisation : la réécriture in-place d'un contrôleur utilisateur reste une question distincte, à trancher séparément (principe 4, préservation du code utilisateur).
  • Aucune écriture dans mvc/routes.py hors commande explicite ne devient permise ; le périmètre reste étroit.

Alternatives écartées

  • Tout basculer en mode affichage (comme make:crud) : respecterait 4.3 à la lettre mais dégraderait l'UX des make:public-*, dont la valeur est de câbler la page d'un geste.
    Corriger ce symptôme plutôt que la portée trop large de 4.3 contredit la règle d'évolution A (retirer la cause, pas le symptôme).
  • Laisser la contradiction implicite : expose à un reproche d'audit récurrent sur une règle « non négociable ».

Référence

  • ADR-023 starter:build canonique (commande retirée depuis par l'ADR-035) : ADR-023.
  • ADR-035 starters réalisés à la main (retrait de la génération) : ADR-035.
  • Correctif de détection robuste du router : FIX-PUBLIC-ROUTES-MARKER-001.
  • Charte : CHARTE_DOC.md (règle 4.3 ; règle d'évolution A).