Files
oto-enterprise-os-dtp/05_deliverables_mvp/rbac/roleprofile_gen
Claude Code DTP Worker a30ff937f0 [DTP-Worker] Sprint 8 · buffer L75 · Reproductibilité checkout propre : hand-off out/ des 4 générateurs RBAC était .gitignore-é (gate rouge en CI, vert local seulement) + durcissement check_artifacts (build produit ⇒ DOIT être suivi par git)
Défaut réel (même classe que le bug regression_run.json corrigé plus tôt) :
les 4 générateurs RBAC (fixtures_gen/userperm_gen/roleprofile_gen/apply_plan)
.gitignore-aient leur out/, alors qu'ils sont audités en archétype `generator`
(critère HANDOFF). En checkout PROPRE (git archive HEAD = ce que voit le runner
Gitea) leur out/ est absent → qa/audit_4big (dont le build relit le out/ de
CHAQUE module) les note 80<95 ⇒ INV7 ⇒ build refusé ⇒ check-artifacts ET
check-regression ROUGES. Ça ne passait qu'en local via les out/ non suivis
laissés par des build manuels.

Fix : committer le out/ des 4 générateurs (build byte-déterministe prouvé ;
apply_plan lit ses frères en process, pas via out/) → alignement sur les 15
autres générateurs ; audit 100/100 en checkout propre.

Durcissement : check_artifacts.sh exige désormais `git ls-files --error-unmatch`
sur chaque fichier produit → un out/ ignoré/non commité devient une erreur
LOCALE honnête au lieu d'une surprise en CI. Bite-proof : git rm --cached d'un
artefact (laissé sur disque) ⇒ exit 1 ; re-add ⇒ exit 0.

Régénéré : quality_report.json (dérive DOC = taille des 4 README édités).
Vérifs : 6 gates verts sur git archive propre ; 534/21 inchangé ; suites OK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-31 01:42:14 +00:00
..

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 (quels verbes sur quel DocType) et plan User Permission (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 (validé par ../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/, commité · byte-déterministe)

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

# 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) — 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).
  4. Vérification HTTP post-déploiement (workflow #3) + audit QA 4Big.

Vérification en-repo

  • python3 -m unittest discover -s tests -v11/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).