Aller au contenu

ADR-038 : Documentation des opt-ins embarquée par paquet

Statut

Accepté, Forge 1.0.0-beta.x (ticket ADR-OPTIN-DOCS-EMBED-001).

La décision de principe est prise.
Le module pilote forge-mvc-stats a prouvé la chaîne de build complète (ticket OPTIN-DOCS-EMBED-STATS-001, commit b6f18d5 : mkdocs build --strict vert, doc montée sous /stats/), sur le modèle séquencé de l'ADR-035.
La convention de slug d'URL ci-dessous est figée avant le déploiement aux onze autres opt-ins.


Date

2026-06-21


Contexte

Forge est distribué en plusieurs paquets PyPI : un cœur forge-mvc et douze briques opt-in (forge-mvc-mfa, forge-mvc-rbac, forge-mvc-workflow, forge-mvc-stats, forge-mvc-files, forge-mvc-images, forge-mvc-iot, forge-mvc-video, forge-mvc-audio, forge-mvc-mail, forge-mvc-pivot, forge-mvc-i18n).
Voir l'ADR-005 (packaging hybride monorepo plus multi-distributions) et l'ADR-004 (périmètre du core minimal).

Aujourd'hui, toute la documentation et tous les parcours welcome des opt-ins vivent dans le docs/ unique du cœur.
Chaque paquet dans packages/ ne porte qu'un README.md.
Le rangement actuel est de plus incohérent et brouille la frontière core / opt-in :

  • docs/iot/ et docs/video/ ont leur propre tronc de premier niveau ;
  • mais MFA, RBAC, Mail, Images sont dissous dans docs/features/, au même niveau que des pages strictement core (crud.md, relations.md, migrations.md) ;
  • la référence des opt-ins est éclatée dans docs/reference/ ;
  • les parcours sont dans docs/starters/welcome-*.

Trois problèmes en découlent :

  1. Frontière core / opt-in invisible (principes 1 et 8).
    Un lecteur ne peut pas distinguer ce qui est livré par forge-mvc de ce qui exige un pip install forge-mvc-xxx.
    features/rbac.md (opt-in) et features/crud.md (core) sont indiscernables.
  2. Rangement non uniforme (principe 11).
    Deux opt-ins ont un tronc dédié, dix autres sont dispersés dans des sections core.
    La charte impose une seule façon officielle de ranger chaque chose.
  3. Couplage de distribution.
    Un utilisateur qui installe seulement forge-mvc-mfa depuis PyPI ne reçoit qu'un mince README.md ; la vraie documentation est ailleurs, dans le dépôt du cœur.
    Toute évolution ou suppression d'un opt-in oblige à éditer le docs/ du core.

Décision

Chaque paquet opt-in possède sa propre documentation, embarquée dans le paquet sous packages/<paquet>/docs/.
Le site MkDocs unique reste la façade publique : il agrège les arbres de documentation des paquets au moment du build, via un plugin d'agrégation (famille mkdocs-monorepo).

Concrètement :

  • Chaque opt-in expose un sous-arbre homogène : présentation, référence et parcours welcome, sous packages/<paquet>/docs/.
  • Le cœur docs/ ne documente plus que le cœur ; les pages opt-in en sont retirées.
  • Le README.md PyPI de chaque paquet pointe vers la page publiée de sa doc.
  • La navigation du site présente un tronc « Opt-ins officiels » qui rassemble les sous-arbres agrégés des douze paquets.

Le site reste unique : on ne fragmente pas en douze sites séparés.
Cela préserve la cohérence pédagogique (les parcours renvoient au cœur) et le choix monorepo de l'ADR-005.
L'agrégation rétablit en revanche la séparation physique et de distribution : le paquet embarque et versionne sa propre doc.


Convention de slug d'URL (figée)

Le plugin d'agrégation utilise le site_name du sous-mkdocs.yml comme préfixe d'URL : la doc d'un opt-in est montée sous /<slug>/.
Le choix du slug est donc une décision de surface publique, figée ici avant le déploiement.

Règle : le slug d'un opt-in est le nom du paquet PyPI privé de son préfixe forge-mvc-.

Paquet Slug Racine d'URL
forge-mvc-stats stats /stats/…
forge-mvc-workflow workflow /workflow/…
forge-mvc-mfa mfa /mfa/…
forge-mvc-rbac rbac /rbac/…
forge-mvc-files files /files/…
forge-mvc-images images /images/…
forge-mvc-iot iot /iot/…
forge-mvc-video video /video/…
forge-mvc-audio audio /audio/…
forge-mvc-mail mail /mail/…
forge-mvc-pivot pivot /pivot/…
forge-mvc-i18n i18n /i18n/…

Justification :

  • court et lisible (/stats/welcome/installation/ plutôt que /forge-mvc-stats/welcome/installation/) ;
  • sans ambiguïté dans le contexte du site (le slug nomme la brique) ;
  • unique : aucun slug n'entre en collision avec un dossier de premier niveau du cœur (reference, features, guide, install…).
    Les slugs iot et video reprennent à l'identique les anciens troncs docs/iot/ et docs/video/, qui sont migrés dans les paquets : l'URL publique ne change pas pour ces deux modules.

Sous-arborescence interne d'un opt-in (figée pour l'homogénéité) :

  • reference.md : page de référence, montée en /<slug>/reference/ ;
  • welcome/ : parcours pédagogique, monté en /<slug>/welcome/…, en conservant la profondeur welcome/<niveau>/<palier>.md pour préserver les liens relatifs vers le cœur (voir « Liens relatifs » ci-dessous).

Note d'implémentation : l'!include doit être déclaré avec une clé (- Titre: '!include packages/<paquet>/mkdocs.yml').
La forme en item nu est ignorée par le merger du plugin (les pages sont préfixées dans la nav mais leurs fichiers ne sont pas agrégés).


Pré-requis anti-casse : valider la chaîne de build, puis migrer par paliers

Deux risques techniques interdisaient une bascule en bloc ; le pilote stats les a levés.

  1. Compatibilité du plugin d'agrégation.
    mkdocs-monorepo-plugin (déclaré dans requirements-docs.txt et requirements-dev.txt) cohabite avec mkdocs-material, le plugin search (langue fr), glightbox et les extensions Markdown actives, et passe mkdocs build --strict (validé par le pilote, 0 avertissement).
  2. Liens relatifs.
    Les parcours welcome opt-in contiennent environ 361 liens relatifs ../.
    Le pilote a montré qu'en conservant la profondeur d'arborescence (<slug>/welcome/<niveau>/ aussi profond que l'ancien starters/welcome-<m>/<niveau>/), la quasi-totalité des liens sortants vers le cœur restent valides sans réécriture ; seuls les liens entrants (depuis le cœur vers la doc migrée) et le lien « vue d'ensemble des starters » sont à recâbler.

Ordre d'exécution :

  1. Outiller (fait) : dépendance de build ajoutée, plugin branché dans mkdocs.yml.
  2. Piloter (fait) : forge-mvc-stats migré, mkdocs build --strict vert.
  3. Généraliser : un paquet par ticket, en appliquant la convention de slug et la sous-arborescence figées ci-dessus.
  4. Nettoyer les pages opt-in résiduelles dans le docs/ du cœur et les références croisées.

Aucune suppression dans le docs/ du cœur n'a lieu avant que le sous-arbre correspondant ne soit servi par l'agrégation.

Dettes à généraliser pendant le déploiement :

  • tests/meta/test_docs_forge_2x_sweep_001.py ne balaie que docs/ ; étendre le balayage à packages/*/docs/ pour que les docs migrées restent couvertes.
  • Le hub docs/starters/index.md pointera de plus en plus dans les arbres montés ; à terme, un tronc de navigation « Opt-ins officiels » dédié.

Conséquences

Positives :

  • Frontière core / opt-in nette, dans la navigation et sur le disque (principes 1 et 8).
  • Rangement uniforme des douze opt-ins (principe 11).
  • Le paquet embarque et versionne sa doc ; le README.md PyPI y pointe.
  • Le cœur est découplé : ajouter ou retirer un opt-in ne touche plus le docs/ du core.

Négatives / coûts :

  • Dépendance de build supplémentaire (plugin d'agrégation) et machinerie mkdocs.yml à maintenir.
  • Effort de migration : déplacement des arbres et réécriture d'environ 361 liens relatifs.
  • Risque de compatibilité du plugin avec le thème et les extensions, à lever par le pilote.

ADR liés

  • Précise l'ADR-005 (packaging hybride monorepo) : la documentation suit la frontière de distribution déjà actée pour le code.
  • Sert les ADR-004 et 016 (périmètre du core minimal, modèle opt-in) en rendant la frontière visible dans la documentation.
  • N'affecte pas l'ADR-035 (parcours manuels) : les parcours welcome restent manuels ; seul leur emplacement change.

Charte appliquée

  • Principe 1 : séparer framework et briques (la doc suit la séparation du code).
  • Principe 8 : noyau minimal, briques opt-in (le cœur ne documente que le cœur).
  • Principe 11 : une seule façon officielle de ranger la doc d'un opt-in.
  • Principe 6 : tester avant d'élargir (pilote obligatoire avant généralisation).
  • Règle A : retirer la cause (la doc opt-in logée dans le cœur), pas le symptôme (le rangement incohérent actuel).