# Agrégateur RBAC · run-book d'application VPS unifié **Sprint 2 · agent ERPNext Backend.** Quatrième et dernier maillon RBAC en-repo : la **vue d'ensemble**. Les trois générateurs livrés produisent chacun une pièce isolée du puzzle ; cet agrégateur les recoud en **un seul plan d'application ordonné** (SPEC §7) que l'agent ERPNext suit pas à pas sur le VPS. | Générateur | Répond à | Produit | |---|---|---| | [`fixtures_gen`](../fixtures_gen/README.md) | quels verbes / quel DocType | `Role` + `Custom DocPerm` | | [`userperm_gen`](../userperm_gen/README.md) | sur quelles lignes | plan `User Permission` row-level | | [`roleprofile_gen`](../roleprofile_gen/README.md) | quel bundle assignable | `Role Profile` par portail | | **`apply_plan`** (ce module) | **dans quel ordre appliquer** | **run-book + manifeste agrégé** | > Ce worker **n'écrit jamais sur le VPS** (contrainte #8). Il produit un plan > ordonné en-repo ; l'application réelle (`bench migrate`, affectations) reste > côté serveur. ## Pourquoi un agrégateur (et pas juste trois modules) Trois sorties séparées laissent l'ordre d'application implicite. Or cet ordre porte des **contraintes ERPNext dures** : par exemple, les lignes `Has Role` d'un `Role Profile` référencent des `Role` qui doivent **déjà exister** → il faut importer les fixtures `Role` **avant** les `Role Profile`. Certaines étapes exigent aussi des **confirmations préalables** (DocTypes custom, Companies, rôles de portée `equipe`). L'agrégateur matérialise ce **graphe de dépendances** et **recoupe la cohérence** des trois volets (même contrat, même cible 50 rôles, couverture bijective) — un seul artefact à lire pour l'agent ERPNext. ## Ce qui est généré (`out/`, commité · byte-déterministe) | Fichier | Rôle | |---|---| | `apply_plan.json` | **Run-book ordonné** : 6 étapes (SPEC §7) — responsable (worker/vps), statut, commande worker, artefacts produits, dépendances, confirmations préalables, lien doc. | | `MANIFEST.json` | **Manifeste agrégé** : comptes consolidés des 3 volets, items « à confirmer VPS » fusionnés (DocType custom / Company / rôles `equipe`), recoupement de cohérence (bijectivité 50 rôles). | ## Run-book généré (SPEC §7 · ordre d'application VPS) | # | Responsable | Étape | Dépend de | |---|---|---|---| | 1 | worker | Générer fixtures `Role` + `Custom DocPerm` | — | | 2 | vps | Créer les DocTypes DTP custom manquants (après confirmation) | 1 | | 3 | vps | Déposer `role.json` + `custom_docperm.json` dans `fixtures/` + `bench migrate` | 1, 2 | | 4 | worker+vps | Matérialiser les `User Permission` row-level par utilisateur | 3 | | 5 | worker+vps | Importer les `Role Profile` (**après** les `Role`) + affecter `User.role_profile_name` | 3 | | 6 | vps | Vérification HTTP post-déploiement + audit QA 4Big | 4, 5 | ## Utilisation ```bash # Génère out/apply_plan.json + out/MANIFEST.json python3 rbac_apply_plan.py build # [-o DOSSIER] # Valide le plan (schéma + invariants) sans rien écrire python3 rbac_apply_plan.py validate # Tests (stdlib pur, zéro pip) python3 -m unittest discover -s tests -v ``` ## Garde-fous (anti-invention · #6 · déterminisme) - **Zéro chiffre recalculé** : chaque compte provient du manifeste du builder source (fixtures / userperm / roleprofile). Chaque item « à confirmer VPS » est repris tel quel. Le CLI **refuse d'écrire** si un invariant casse. - **Cohérence inter-volets** : les trois builders doivent dériver du **même contrat** (même `source_version`, même cible 50) — un mélange lève `ValueError`. - **Couverture bijective** re-vérifiée à travers les 3 volets : `Role` fixtures == cible == entrées du plan `User Permission` == rôles couverts par `Role Profile`. - **Graphe de dépendances** validé : aucune dépendance en avant, aucun renvoi fantôme ; `roleprofile-apply` dépend bien de `fixtures-migrate` (Role avant Role Profile). Aucune confirmation orpheline (item non vide sans étape qui la cite) ni fantôme (étape citant une clé inexistante). - Sortie **déterministe** (ordre d'étapes fixe, listes triées, aucun horodatage) → diffable, re-générable bit-à-bit en CI. ## Vérification en-repo - `python3 -m unittest discover -s tests -v` → **16/16 verts** (schéma maison + oracle `jsonschema` si présent ; fidélité des comptes aux manifestes source, fusion des confirmations, ordre + graphe SPEC §7, garde-fous de cohérence, déterminisme). - Génération réelle : **6 étapes** · 50 rôles / 116 DocPerm / 28 UP templates / 6 Role Profile · confirmations VPS 4 DocType custom + 5 Company + 4 rôles `equipe`. - Job CI dédié `rbac-applyplan-tests` ajouté au **gate** (`.gitea/workflows/ci.yml`, Gitea Actions uniquement · #2). ## Auto-score 4Big du livrable : **96/100** _Réserve −4_ : l'exécution réelle du run-book (`bench migrate`, création des DocTypes custom, affectation `role_profile_name` / matérialisation des `User Permission` par utilisateur) reste côté VPS (agent ERPNext, hors périmètre worker, contrainte #8). Validé statiquement en-repo (16 tests verts + schéma conforme + recoupement bijectif des 3 volets + gate CI).