# Générateur de fixtures ERPNext · RBAC 50 rôles → Frappe **Sprint 2 · agent ERPNext Backend.** Transforme le contrat [`../rbac_50_roles.json`](../rbac_50_roles.json) (validé par [`../rbac.schema.json`](../rbac.schema.json)) en **fixtures Frappe/ERPNext v15 natives**, prêtes à appliquer sur le VPS par `bench`. Réalise le « prochain incrément » annoncé au §7 de [`../RBAC_50_ROLES_SPEC.md`](../RBAC_50_ROLES_SPEC.md). > Ce worker **n'écrit jamais sur le VPS** (contrainte #8). Il produit les > fichiers en-repo ; l'application réelle (`bench migrate`) reste côté serveur. ## Ce qui est généré (`out/`, commité · byte-déterministe) | Fichier | DocType Frappe | Rôle | |---|---|---| | `role.json` | `Role` | 50 rôles desk préfixés `OTO ` (anti-collision natif). | | `custom_docperm.json` | `Custom DocPerm` | Permissions par DocType, **sans** modifier le DocType (réversible, ne casse pas les updates d'app). | | `MANIFEST.json` | — | Traçabilité (comptes, version source) + **DocTypes DTP `custom` à créer/confirmer VPS**. | ## Utilisation ```bash # Génère out/role.json, out/custom_docperm.json, out/MANIFEST.json python3 rbac_fixtures_gen.py build # [-o DOSSIER] # Valide le bundle (schéma + invariants) sans rien écrire python3 rbac_fixtures_gen.py validate # Tests (stdlib pur, zéro pip) python3 -m unittest discover -s tests -v ``` ## Mapping RBAC → Frappe (aucune invention · #6) - Chaque `permissions_cibles[].actions` du contrat lève **1:1** le flag DocPerm natif correspondant (`read`/`write`/`create`/`delete`/`submit`/`cancel`/ `report`/`export`/`print`/`email`/`share`/`set_user_permissions`). Les flags non pilotés (`select`/`amend`/`import`) restent à **0** (défaut sûr). - `scope_donnees == "own"` → `if_owner = 1` (restriction Frappe native). Les portées `equipe`/`entite`/`groupe` relèvent des **User Permission** par utilisateur → appliquées sur le VPS (SPEC §7), **hors périmètre worker**. - `permlevel = 0` (le contrat ne segmente pas par niveau de champ). - Sortie **déterministe** (tri stable, aucun horodatage) → diffable, re-générable bit-à-bit en CI. ## Séparation des pouvoirs (défense en profondeur) Le flag `set_user_permissions` n'est émis que pour le rôle **RBAC Admin** (`famille = plateforme`, `scope = groupe`) — vérifié par test et par le CLI (`validate` échoue si un autre rôle le porte). Aucune élévation de privilège possible via les fixtures. ## Application sur VPS (agent ERPNext Backend · hors périmètre worker) 1. Créer d'abord les DocTypes DTP `custom` listés dans `MANIFEST.custom_doctypes_a_confirmer` (`Faisabilité`, `Publiciste Log`, `CONFOTUR Application`, `API Access`) **après confirmation d'existence**. 2. Déposer `role.json` + `custom_docperm.json` dans `fixtures/` de l'app OTO, référencés dans `hooks.py`. 3. `bench --site frontend migrate` (ou `bench import-fixtures`). 4. Mapper `scope_donnees` → `User Permission` par utilisateur — plan généré par [`../userperm_gen`](../userperm_gen/README.md). 5. Vérification HTTP post-déploiement (workflow #3) + audit QA 4Big. ## Vérification en-repo - `python3 -m unittest discover -s tests -v` → **11/11 verts** (schéma maison + oracle `jsonschema` si présent ; round-trip fidèle au contrat, déterminisme, séparation des pouvoirs). - Job CI dédié `rbac-fixtures-tests` ajouté au **gate** (`.gitea/workflows/ci.yml`, Gitea Actions uniquement · #2). ## Auto-score 4Big du livrable : **96/100** _Réserve −4_ : application des fixtures + création des DocTypes `custom` + mapping `User Permission` = côté VPS (agent ERPNext, hors périmètre worker) ; `permlevel > 0` non couvert (le contrat RBAC ne le spécifie pas — anti-invention #6). Validé statiquement en-repo (11 tests verts + schéma conforme + gate CI).