Files
oto-enterprise-os-dtp/05_deliverables_mvp/rbac/roleprofile_gen
Claude Code DTP Worker 70e022ccd6 [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>
2026-07-30 04:04:04 +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/, 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

# 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).