[DTP-Worker] Sprint 2 · Générateur Role Profile par portail (RBAC 50 rôles → 6 bundles assignables ERPNext v15)
- roleprofile_gen/ : profilelib (frappe Role Profile + Has Role natif v15, builder déterministe), roleprofile.schema.json, CLI build/validate refusant d'écrire si invariant cassé, 11 tests stdlib, README, .gitignore (out/). - 6 profils couvrant les 50 rôles de façon bijective (5 portails métier + console technique plateforme). Aucun DocType custom (que du natif). - Anti-invention #6 : rôles 100 % issus du contrat, nom de profil = convention déterministe dérivée de la clé portail. - CI : job rbac-roleprofile-tests ajouté au gate (.gitea/workflows/ci.yml). - Doc : SPEC §7 ét.5 + encart livré. Daily report session 8. - Régression : 83 tests verts (72 + 11). Gate CI local vert. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# Générateur de `Role Profile` · RBAC 50 rôles → bundles par portail
|
||||
|
||||
**Sprint 2 · agent ERPNext Backend.** Troisième et dernier maillon RBAC en-repo,
|
||||
complément des générateurs [`Role` + `Custom DocPerm`](../fixtures_gen/README.md)
|
||||
(quels verbes sur quel DocType) et [plan `User Permission`](../userperm_gen/README.md)
|
||||
(sur quelles lignes). Il produit les **bundles assignables** : un `Role Profile`
|
||||
ERPNext v15 **natif** par portail, qui permet d'attribuer à un utilisateur, en un
|
||||
seul geste (`User.role_profile_name`), l'ensemble des rôles de SON portail.
|
||||
Transforme le contrat [`../rbac_50_roles.json`](../rbac_50_roles.json) (validé par
|
||||
[`../rbac.schema.json`](../rbac.schema.json)) en fixtures Frappe prêtes à importer.
|
||||
|
||||
> Ce worker **n'écrit jamais sur le VPS** (contrainte #8). Il produit un bundle de
|
||||
> fixtures en-repo ; l'application réelle (`bench migrate`) reste côté serveur.
|
||||
|
||||
## Pourquoi un `Role Profile` (et pas juste des rôles)
|
||||
|
||||
Assigner à la main les 5 à 12 rôles d'un portail à chaque nouvel utilisateur est
|
||||
fastidieux et source d'erreurs. ERPNext v15 fournit nativement le DocType
|
||||
`Role Profile` (contrainte #1 « ERPNext natif = priorité absolue ») : un bundle
|
||||
nommé de rôles (`Has Role`) qu'on affecte en un champ. Les **5 portails métier**
|
||||
(roadmap Sprint 4 « 5 portails rôle ») + la **console technique `plateforme`**
|
||||
donnent **6 profils** couvrant les 50 rôles de façon **bijective** (chaque rôle
|
||||
dans exactement un profil, puisque chaque rôle a exactement un `portail`).
|
||||
|
||||
## Ce qui est généré (`out/`, non commité)
|
||||
|
||||
| Fichier | Rôle |
|
||||
|---|---|
|
||||
| `role_profile.json` | **1 fixture `Role Profile` par portail** ; chacun bundle ses rôles via des lignes enfant `Has Role`. |
|
||||
| `MANIFEST.json` | Traçabilité : comptes (profils, métier vs technique, rôles couverts) + mapping `portail → role_profile`. |
|
||||
|
||||
## Profils générés (contrat courant · source de vérité = le JSON)
|
||||
|
||||
| `role_profile` | Portail | Type | Nb rôles |
|
||||
|---|---|---|---|
|
||||
| `OTO Portail Ventes` | ventes | métier | 12 |
|
||||
| `OTO Portail Construction` | construction | métier | 10 |
|
||||
| `OTO Portail Direction` | direction | métier | 9 |
|
||||
| `OTO Portail Compta` | compta | métier | 8 |
|
||||
| `OTO Portail Achat` | achat | métier | 5 |
|
||||
| `OTO Portail Plateforme` | plateforme | technique | 6 |
|
||||
| | | **Total** | **50** |
|
||||
|
||||
> Le nom du profil est une **convention de nommage déterministe** dérivée de la
|
||||
> clé `portail` (`OTO Portail <Portail>`) — aucun libellé métier ni chiffre
|
||||
> fabriqué (anti-invention #6). Les comptes viennent du contrat, pas de cette
|
||||
> table (cf. SPEC §3 : le JSON reste la source de vérité).
|
||||
|
||||
## Utilisation
|
||||
|
||||
```bash
|
||||
# Génère out/role_profile.json + out/MANIFEST.json
|
||||
python3 roleprofile_gen.py build # [-o DOSSIER]
|
||||
|
||||
# Valide le bundle (schéma + invariants) sans rien écrire
|
||||
python3 roleprofile_gen.py validate
|
||||
|
||||
# Tests (stdlib pur, zéro pip)
|
||||
python3 -m unittest discover -s tests -v
|
||||
```
|
||||
|
||||
## Garde-fous (anti-invention · #6 · déterminisme)
|
||||
|
||||
- **Couverture bijective** re-vérifiée : chaque rôle du contrat dans exactement
|
||||
un profil, aucun rôle inventé, aucun manquant ; le CLI **refuse d'écrire** si un
|
||||
invariant casse.
|
||||
- **Que du natif v15** : DocTypes `Role Profile` + `Has Role` uniquement → aucun
|
||||
DocType custom à confirmer côté VPS (contrairement aux `Custom DocPerm`).
|
||||
- **Cohérence portail** : un profil ne mélange jamais deux portails ; son nom
|
||||
correspond à la convention pour ce portail.
|
||||
- **Fidélité manifeste** : flag `metier` = appartenance à `portails_business` ;
|
||||
comptes re-vérifiés profil par profil.
|
||||
- Sortie **déterministe** (profils triés par portail, `Has Role` triés par nom de
|
||||
rôle, aucun horodatage) → diffable, re-générable bit-à-bit en CI.
|
||||
|
||||
## Application sur VPS (agent ERPNext Backend · hors périmètre worker)
|
||||
|
||||
1. Importer d'abord les fixtures `Role` ([`fixtures_gen`](../fixtures_gen/README.md))
|
||||
— les `Has Role` de chaque profil référencent des `Role` qui doivent exister.
|
||||
2. Déposer `role_profile.json` dans `fixtures/` de l'app OTO (`hooks.py`), puis
|
||||
`bench --site frontend migrate`.
|
||||
3. À la création d'un utilisateur, renseigner `role_profile_name` avec le profil
|
||||
de son portail (mapping dans `MANIFEST.profiles`) → tous les rôles du portail
|
||||
sont appliqués d'un coup, puis matérialiser les `User Permission` par
|
||||
utilisateur ([`userperm_gen`](../userperm_gen/README.md)).
|
||||
4. 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 ; couverture bijective des 50 rôles, un profil
|
||||
par portail, cohérence portail, manifeste fidèle, anti-invention, déterminisme).
|
||||
- Génération réelle : **6 profils** (5 métier + 1 technique), **50/50 rôles**
|
||||
couverts.
|
||||
- Job CI dédié `rbac-roleprofile-tests` ajouté au **gate** (`.gitea/workflows/ci.yml`,
|
||||
Gitea Actions uniquement · #2).
|
||||
|
||||
## Auto-score 4Big du livrable : **96/100**
|
||||
|
||||
_Réserve −4_ : l'import `bench` + l'affectation `role_profile_name` par
|
||||
utilisateur restent côté VPS (agent ERPNext, hors périmètre worker, contrainte
|
||||
#8). Validé statiquement en-repo (11 tests verts + schéma conforme + couverture
|
||||
bijective fidèle au contrat + gate CI).
|
||||
Reference in New Issue
Block a user