0083 — layers source unique de l'ordre : presets en alias, plus de chemins nommés par défaut
Accepted (2026-06-19) — livraison INCRÉMENTALE. Le code est livré
(nestor/layers.py, source unique de l’ordre) ; promu depuis
Proposed (2026-06-17).
Contexte
Section intitulée « Contexte »L’ADR 0069 a introduit layers : un
ensemble de couches dont l’ordre est DÉRIVÉ du graphe atomique unique
(ADR 0066, resolve_layers →
topo_sort). Mais il a conservé les presets de chemin comme étape
transitoire (son point 8) :
socle/atlas/storage-real/cluster-dataops/atlas-ceph/ha-3cp gardent
une séquence figée (_PATH_TAIL dans nestor/plan.py), et default_target
re-mappe l’ensemble de couches déclaré vers un nom de preset.
Cela laisse deux sources de vérité de l’ORDRE des couches en parallèle :
_PATH_TAIL— tables ordonnées par preset, transcription manuelle des arms debench/lima/run-phases.sh;- le graphe atomique (
resolve_layers) — la source que l’ADR 0069 voulait unique.
test_parity ne fait que constater leur égalité ; il ne supprime pas le
doublon. Le « À revoir si » de l’ADR 0069 anticipait précisément ce dénouement :
« le mapping layers → preset devient un frein → rendre les presets de simples
raccourcis ».
Le doublon a produit un bug vécu. default_target mappe approximativement
(dataops ∈ layers → atlas) : pour une topo layers: [dataops, mlflow], il
rend atlas, dont la séquence figée n’inclut PAS mlflow. Résultat : next et
preview divergent — preview (qui dérive la vraie séquence via
resolve_layers, branche de rustine) voit « MLflow à installer », tandis que
next (sur le preset atlas) propose « rejouer up » sur un banc déjà monté.
Les branches layers_seq de cmd_up et cmd_preview sont des rustines de ce
même décalage.
Décision
Section intitulée « Décision »layers (graphe atomique) devient la SEULE source de l’ordre. Les presets de
chemin ne sont plus dérivés par défaut.
-
default_target(topo)rend TOUJOURSlayers(suppression du mapping versatlas/socle/metrics/atlas-ceph). La séquence vient exclusivement deresolve_layers(topo.declared_layers, backend)+ le socle dérivé. Plus de « second routeur » qui peut diverger du montage réel. -
ha-3cpcesse d’être un chemin nommé : c’est une propriété de la TOPOLOGIE. La HA se déduit detopo.is_ha_control_plane(≥2 control-planes, ADR 0047/0055). Son amorçage (bootstrap-ha,join-cp: kube-vip + join etcd) n’est PAS réductible à des layers (aucun nœud dans le graphe atomique, aucun arm unitaire) : il devient un socle dérivé —expected_phase_sequenceproduit, pour une topo HA,[up, bootstrap-ha, join-cp] + queue resolve_layers. À l’exécution,cmd_updélègue le socle HA à l’armrun-phases.sh ha-3cpinchangé (l’orchestration VIP/etcd reste portée parnestor/ha.py), puis enchaîne la queue.ha-3cpdisparaît comme target saisi par l’utilisateur ; il survit comme détail d’implémentation du moteur bash, dérivé de la topologie. -
atlasdevient un alias de LAYERS (LAYER_PHASES,nestor/layers.py), valant la chaîne MLOps complète[metrics, obs, gitops, dataops, gitops-seed, mlflow](obs= monitoring,metrics= metrics-server ;gitops-seedlisté explicitement car phase de queue non tirée par la clôture de[gitops]). Une topo déclarelayers: [atlas]pour toute la chaîne.resolve_layersl’ordonne via le graphe :- local-path :
storage-simple, metrics-server, monitoring, gitops, dataops, gitops-seed, mlflow; - ceph :
ceph, sc, datalake, metrics-server, monitoring, gitops, dataops, gitops-seed, mlflow.
C’est l’ancien
atlas/atlas-cephplusmlflow(ADR 0082, brique livrée) ; l’atlas-ceph gagne aussimetrics-server(inoffensif, déjà présent en local-path) — sur-ensemble cohérent assumé, pas une régression de couche. - local-path :
-
profile: atlasn’existe PAS :profilereste le préfixe cumulatifbase ⊂ metrics ⊂ store ⊂ obs ⊂ dataops(ADR 0039) ;atlasn’est pas un préfixe (il ajoute gitops/seed/mlflow hors chaîne). On l’expose donc uniquement vialayers: [atlas], sans casser l’invariant du profil scalaire. -
run-phases.shreste inchangé (moteur bash, ADR 0049/0063). Hors HA,cmd_uppasse par l’arm génériquelayers <séquence>(Python décide l’ordre, bash exécute). Les arms nommés (atlas,atlas-ceph,storage-real,cluster-dataops,metrics,socle) survivent pour--target <nom>explicite et la rétrocompat des scénarios/bench, mais ne sont plus la cible par défaut.
Conséquences
Section intitulée « Conséquences »- Une seule source de vérité de l’ordre :
_PATH_TAIL,_CEPH_PATHS,_STORAGE_LAYER,_LOCAL_PATH_NEEDS_STORAGEdisparaissent denestor/plan.py. Le drift potentiel entre presets et graphe est supprimé à la racine. next/preview/upconvergent par construction : tous dérivent la séquence viaresolve_layersquand aucun--targetn’est forcé → le bugnextvspreviewest dissous (plus deux routeurs).- HA = propriété de la topologie (cohérent avec ADR 0069 point 6 qui la
disait déjà « structurelle, dérivée des nœuds ») : on ne déclare plus un
chemin
ha-3cp, on déclare ≥2 control-planes. test_paritychange de garantie : il prouve désormais queresolve_layers(alias)reproduit la séquence de référence (le filet anti-drift demeure, sur la nouvelle source unique).- Aucune destruction de banc : refactor Python-pur (run-phases.sh intact) ;
preuve par
pytest/batssans banc, run from-scratch différé (ADR 0034/0052, banc Ceph détruit). - ADR amendés : 0069 (son point 8 «
presets transitoires » est résorbé ; son « À revoir si » est réalisé),
0056 (
default_targetne mappe plus vers des presets), 0047/0055 (HA dérivée de la topologie, plus un chemin nommé). 0066 reste le socle technique réutilisé, inchangé.
À revoir si
Section intitulée « À revoir si »- Un preset nommé redevient nécessaire comme alias de layers (pas de chemin)
: l’ajouter à
LAYER_PHASEScommeatlas, jamais à_PATH_TAIL(supprimé). - L’amorçage HA gagne un arm unitaire dans le graphe : le socle HA dérivé
pourrait alors passer aussi par l’arm
layers, supprimant le dernier cas spécial bash.
Alternatives écartées
Section intitulée « Alternatives écartées »- Garder les presets comme alias de chemin ordonnés (conserver
_PATH_TAIL) : laisse les deux sources de vérité, le bugnext/previewpeut revenir. Rejeté — c’est exactement la dette que cet ADR solde. - Supprimer aussi les noms (
atlas…) entièrement : chaque topo listerait toutes ses phases (layers: [metrics, obs, gitops, dataops, gitops-seed, mlflow]). Verbeux, perd le vocabulaire métier ; rejeté au profit de l’aliasatlascôté layers. ha-3cpreste un chemin nommé à part : moins risqué (périmètre réduit) mais perpétue un « chemin » qui est en réalité une topologie ; rejeté — la HA est une propriété du control-plane, pas une cible de montage.- Réduire l’amorçage HA à des layers (
bootstrap-ha/join-cpcomme phases du graphe) : exigerait des arms unitaires et des nœuds graphe pour le VIP/join etcd ; sur-dimensionné, reporté (cf. « À revoir si »).