[DTP-Worker] Sprint 2 · ERPNext RBAC 50 rôles (schéma + data + spec + gate)

Livrable Sprint 2 (roadmap §S2 l.38 « RBAC 50 rôles configuration »,
GAP_ANALYSIS §3.4). Seul deliverable S2 100% autorable en-repo — les clones
Frontend/CRM dépendent des layouts LIVE (VPS).

- rbac/rbac.schema.json — contrat JSON-Schema draft-07 (sous-ensemble validateur
  maison, zéro pip) : 50 rôles, DocPerm par DocType, scope User Permission.
- rbac/rbac_50_roles.json — 50 rôles × 5 portails métier + console plateforme,
  mappés aux entités CLAUDE.md, ciblant des DocTypes ERPNext v15 natifs.
- rbac/RBAC_50_ROLES_SPEC.md — design RBAC 3 niveaux + séparation des pouvoirs +
  procédure d'application VPS (fixtures bench, hors périmètre worker).
- rbac/tests/test_rbac.py — 10 tests unittest (réutilise le validateur
  Publiciste, pas de doublon) : 50 rôles exacts, unicité, 5 portails, anti-
  élévation de privilège. Oracle jsonschema si présent.
- ci.yml — job rbac-tests ajouté au gate (Gitea Actions uniquement).
- GAP_ANALYSIS §3.4 + daily report 2026-07-30 (session 4) mis à jour.

Anti-invention #6 : aucun plafond monétaire inventé ; DocTypes non natifs
marqués custom → à confirmer VPS. Gate local vert (guard/json/docs + 10 tests
RBAC + 23 tests Publiciste régression).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Code DTP Worker
2026-07-30 02:05:54 +00:00
parent f0a7d71357
commit cc3e5aef0e
8 changed files with 1291 additions and 4 deletions
+3 -3
View File
@@ -83,9 +83,9 @@ et la cible plancher **4-5 semaines**.
### 4 · ERPNext Backend Agent — 🟡 Refactor (gain ~35 %)
- **Existe** : site `frontend` (`erpnext-backend-1`), apps `otov7_platform` + `otov7_construction` + `erpnext` v15.112 + `frappe` v15.112, modules `crm/ crm_native/ api/ config/ audit_console.py`.
- **Gap** : RBAC 50 rôles non configuré ; e-CF DGII (Compupar) non intégré ; commissions vendeurs auto absentes ; DocType « Faisabilité » (version + score) manquant.
- **À faire** : cartographie DocTypes (⚠ à confirmer VPS) → RBAC 50 rôles → e-CF → workflows.
- **Sprint** : S2 (RBAC) → S4 (e-CF + commissions).
- **Gap** : ~~RBAC 50 rôles non configuré~~**design livré S2** (`rbac/` : `rbac_50_roles.json` + `rbac.schema.json` + spec + 10 tests) ; application fixtures = VPS ; e-CF DGII (Compupar) non intégré ; commissions vendeurs auto absentes ; DocType « Faisabilité » (version + score) manquant.
- **À faire** : cartographie DocTypes (⚠ à confirmer VPS) → RBAC 50 rôles (design) → application fixtures VPS → e-CF → workflows.
- **Sprint** : S2 (RBAC ✅ design) → S4 (e-CF + commissions).
### 5 · Frontend Console Agent — 🟡 Refactor (gain ~55 %)
- **Existe** : `portal/*.html`, pages Frappe `www/` (wag-home, waf-home, pole/, projets/), tokens luxury `#0a0a12`/`#f0b429` (Fraunces + Cormorant Garamond), 5 logos officiels.
@@ -139,3 +139,49 @@ Rapport écrit dans `05_deliverables_mvp/daily_reports/` (chemin canonique fixé
---
**Auto-score 4Big du livrable Publiciste (parser) : 95/100.** Réserve 5 : exécution contre `data_room/` réel différée (VPS) ; triggers/notifications/EN-ES = livrables Semaines 4-6 ; validé statiquement en-repo (23 tests verts + gate CI vert + schéma conforme).
---
# Daily Report · 2026-07-30 · Claude Code DTP Worker (session 4)
**Session** : `20260730_015634`
## Tâche exécutée
**Sprint 2 · Livrable ERPNext Backend « RBAC 50 rôles »**
(roadmap `04_roadmap/ROADMAP_8_WEEKS_OR_LESS.md` §Sprint 2 l.38 · `GAP_ANALYSIS_SPRINT1` §3.4 · suggérée par session 3).
## Contexte / analyse
- Relu `CLAUDE.md`, `ROADMAP_8_WEEKS_OR_LESS.md`, `GAP_ANALYSIS_SPRINT1.md`, daily reports sessions 1-3, `AGENT.md` ERPNext Backend + Frontend Console, `AGENTS_EXISTING_ASSETS.md` §4-6, `projets_master.schema.json`, `validator.py`, `ci.yml`.
- **Sprint 1 bouclé côté repo** ; Sprint 2 : 3 deliverables. Frontend (clone 5 entités) + CRM (pipeline) dépendent des layouts LIVE `/waf-home` / `/crm.html` (VPS). **RBAC 50 rôles = seul deliverable S2 100 % autorable en-repo** comme spec de conception machine-lisible → priorité évidente. Dépendance amont des 5 portails rôle (S4) et du workflow vente.
## Réalisé — module `05_deliverables_mvp/rbac/`
- `rbac.schema.json` — contrat JSON-Schema draft-07 (sous-ensemble supporté par le validateur maison, **zéro pip**) : 50 rôles, `id` kebab, `erpnext_role_name` préfixe `OTO `, `permissions_cibles[]` (DocType + verbes Frappe), `scope_donnees` (own/equipe/entite/groupe), `cible_rbac_roles` const 50.
- `rbac_50_roles.json`**50 rôles** répartis sur 5 portails métier (roadmap S4) + 1 console technique (`plateforme`), mappés aux **entités CLAUDE.md** (WAF/WA SRL/AC Arias Cuevas/Consortium ECR DR/Helios RD/Ploutos/9060 QC/Groupe). Permissions ciblant des **DocTypes ERPNext v15 natifs** (Lead/Opportunity/Quotation/Sales Order/Purchase Order/Journal Entry/Salary Slip…) + DocTypes DTP marqués `custom: true` (à confirmer VPS).
- `RBAC_50_ROLES_SPEC.md` — design : modèle RBAC 3 niveaux (Role · DocPerm · User Permission), cartographie portails/familles/entités, conformité contraintes #1/#3/#6/#8, **séparation des pouvoirs** (`set_user_permissions` réservé au RBAC Admin), procédure d'application VPS (fixtures `bench`, hors périmètre worker).
- `tests/test_rbac.py`**10 tests `unittest` (stdlib)** : **réutilise le validateur Publiciste** (pas de duplication · workflow #5) + oracle `jsonschema` si présent ; vérifie exactement 50 rôles, unicité `id`/nom Frappe, couverture des 5 portails, anti-élévation de privilège.
- **CI** : job `rbac-tests` ajouté au **gate** de `.gitea/workflows/ci.yml` (Gitea Actions uniquement · #2).
- `GAP_ANALYSIS_SPRINT1.md` §3.4 mis à jour (RBAC design livré S2).
## Anti-invention (#6) appliqué
- **Aucun chiffre/plafond monétaire inventé** : seuls rôles, entités et DocTypes natifs. Plafonds d'approbation volontairement non chiffrés (à définir avec la Direction sur pièces).
- DocTypes non natifs marqués `custom: true`**existence à confirmer VPS** avant application (respect de l'interdit « documenter code sans vérifier existence courante »).
## Vérifications effectuées (en-repo, sans toucher au VPS)
- **10/10 tests RBAC verts** (schéma maison **+** oracle `jsonschema` installé → concordance draft-07 confirmée).
- **Gate CI local vert (exit 0)** : `guard_constraints.sh`, `validate_json.sh` (inclut `rbac_50_roles.json`), `check_docs.sh` (0 lien cassé ; spec RBAC porte son auto-score 4Big).
- **Régression** : 23/23 tests Publiciste toujours verts (réutilisation du validateur sans effet de bord).
## Non fait (hors périmètre worker · touche au VPS)
- Génération + application des **fixtures `Role`/`Custom DocPerm`** sur `erpnext-backend-1` (`bench migrate`) → agent ERPNext Backend.
- Création des DocTypes DTP `custom` (`Faisabilité`, `Publiciste Log`, `CONFOTUR Application`, `API Access`) après confirmation VPS.
- Mapping `scope_donnees``User Permission` par utilisateur → VPS.
- Cartographie DocTypes réels `otov7_platform` (dernier critère S1) → ERPNext sur VPS.
## Prochaine tâche suggérée
- ERPNext S2 : **générateur de fixtures** `rbac_50_roles.json → fixtures/` (même patron que le Publiciste, autorable en-repo).
- Ou Faisabilité S2 : générateur 4 volets auto consommant le template v1.0 (produit les `data_room/PXX/` consommés par le parser Publiciste).
- Ou Frontend/CRM S2 : nécessite les layouts LIVE (VPS) → hors périmètre worker.
---
**Auto-score 4Big du livrable RBAC 50 rôles : 95/100.** Réserve 5 : application fixtures + DocTypes `custom` + `User Permission` = côté VPS (agent ERPNext, hors périmètre) ; plafonds monétaires non chiffrés (anti-invention #6). Validé statiquement en-repo (10 tests verts + schéma conforme + gate CI vert).
+5
View File
@@ -0,0 +1,5 @@
# Artefacts Python (jamais commit — reproductibles).
__pycache__/
*.pyc
# Fixtures Frappe générées côté VPS (hors périmètre worker).
fixtures/
@@ -0,0 +1,152 @@
# Spec RBAC · 50 rôles · OTO Enterprise OS DTP
> **Livrable Sprint 2 · ERPNext Backend** (roadmap
> [`../../04_roadmap/ROADMAP_8_WEEKS_OR_LESS.md`](../../04_roadmap/ROADMAP_8_WEEKS_OR_LESS.md)
> §Sprint 2 l.38 : _« ERPNext Backend : RBAC 50 rôles configuration »_ ·
> [`../GAP_ANALYSIS_SPRINT1.md`](../GAP_ANALYSIS_SPRINT1.md) §3.4 gap ERPNext).
>
> **Date** : 2026-07-30 · **Auteur** : Claude Code DTP Worker · **Version** : 1.0.0
---
## 1. Objet
Design **machine-lisible** des **50 rôles RBAC** (contrainte CLAUDE.md « RBAC 50 rôles »)
à créer nativement dans Frappe/ERPNext v15. Le contrat de données est
[`rbac.schema.json`](rbac.schema.json) ; les données sont
[`rbac_50_roles.json`](rbac_50_roles.json). Ce document ne touche **jamais la
production** : il définit la **cible** que l'agent ERPNext Backend appliquera sur
le VPS via `bench` / fixtures (voir §7).
**Priorité ERPNext natif** (contrainte #1) : chaque rôle est un DocType `Role`
Frappe standard — **aucun** RBAC externe.
**CRM = ERPNext natif** (jamais EspoCRM ni HubSpot — contrainte #3).
## 2. Modèle RBAC
Le RBAC Frappe combine trois niveaux, tous couverts par le schéma :
| Niveau Frappe | Champ du schéma | Rôle |
|---|---|---|
| **Role** (DocType) | `erpnext_role_name` | Un DocType `Role` par ligne, préfixe `OTO ` (anti-collision natif). |
| **Permissions par DocType** | `permissions_cibles[]` | Verbes Frappe (`read`/`write`/`create`/`submit`/`cancel`/`report`/…) par DocType. |
| **Row-level** (User Permission) | `scope_donnees` | `own` · `equipe` · `entite` (Company) · `groupe` (consolidé). |
**Défense en profondeur** : le pouvoir `set_user_permissions` (gestion des
habilitations) est **réservé** au seul rôle `OTO Plateforme RBAC Admin`
(`scope_donnees = groupe`, `famille = plateforme`) — séparation des pouvoirs
vérifiée par test automatisé.
## 3. Cartographie portails ↔ familles
Les **5 portails métier** (roadmap Sprint 4 « 5 portails rôle ») + **1 console
technique transversale** (`plateforme`, hors du compte de 5) :
| Portail | Familles rattachées | Nb rôles |
|---|---|---|
| **direction** | direction, finance (CFO), faisabilite (analyste), legal | 10 |
| **ventes** | ventes, marketing | 12 |
| **construction** | construction, faisabilite (rendu/IFC/économiste) | 10 |
| **achat** | achat | 5 |
| **compta** | finance | 8 |
| **plateforme** _(technique)_ | plateforme | 5 |
| | **Total** | **50** |
> Répartition indicative issue de `rbac_50_roles.json` ; la source de vérité reste
> le JSON (le test impose exactement 50 rôles et la couverture des 5 portails).
## 4. Cartographie rôles ↔ entités (CLAUDE.md §Entités)
Chaque rôle porte une `entite_principale`. « Groupe » = périmètre consolidé
transversal (direction, contrôle de gestion, audit UAF, BI).
| Entité | Exemples de rôles |
|---|---|
| **WAF** (holding) | Président, Directeur Juridique, Agent ONAPI |
| **WA SRL** | Contrats de vente, Achats, Comptable général, Fiscaliste e-CF, Analyste faisabilité |
| **AC Arias Cuevas** | Directeur/Chef de projet Construction, Ingénieur, Économiste, Magasinier |
| **Consortium ECR DR** (paymaster RH) | Gestionnaire Paie |
| **Helios RD** (marque publique) | Directeur des Ventes, Conseiller, Marketing, Comptable clients AR |
| **Ploutos** (patrimoine/monétaire) | Trésorier |
| **9060 QC** (World Activities Cdn.) | DevOps, RBAC Admin, QA, OTOIA, Mobile |
| **Groupe** (consolidé) | DG, CFO, COO, CCO, Conseil, Contrôle de gestion, Audit UAF, BI |
## 5. Les 50 rôles (résumé)
> Détail complet (permissions par DocType, modules, scope) dans
> [`rbac_50_roles.json`](rbac_50_roles.json).
**Direction / Gouvernance (6)** — Président WAF · Directeur Général · CFO · COO ·
CCO · Conseil d'Administration (lecture).
**Ventes (8)** — Directeur des Ventes · Chef d'Équipe · Conseiller · Courtier
externe · Coordinateur Réservations · Gestionnaire Contrats · Coordinateur
CONFOTUR · Support Après-Vente.
**Marketing (4)** — Directeur Marketing · Publiciste (agent) · SEO · Social.
**Construction (7)** — Directeur · Chef de Projet · Ingénieur · Architecte ·
QA/QC · Coordinateur BIM · Superviseur Sous-traitants.
**Achat (5)** — Directeur · Acheteur · Gestionnaire Fournisseurs · Magasinier ·
Contrôleur Réception.
**Finance / Compta (8)** — Contrôleur de Gestion · Comptable Général · AP · AR ·
Trésorier (Ploutos) · Paie (Consortium ECR DR) · Fiscaliste e-CF · Audit UAF.
**Faisabilité / AEC (4)** — Analyste Faisabilité · Rendu 3D · IFC/Speckle ·
Économiste de la Construction.
**Legal (2)** — Directeur Juridique · Agent ONAPI.
**Plateforme technique (6)** — DevOps · RBAC Admin · QA · OTOIA (système) ·
Mobile · BI.
_(6+8+4+7+5+8+4+2+6 = 50.)_
## 6. Conformité aux contraintes CLAUDE.md
| # | Contrainte | Application ici |
|---|---|---|
| 1 | ERPNext natif prioritaire | 100 % DocType `Role` Frappe, aucun RBAC externe. |
| 3 | CRM = ERPNext natif | Rôles ventes → `Lead`/`Opportunity`/`Quotation`/`Customer` natifs. |
| 6 | Zéro invention | Aucun chiffre/plafond monétaire inventé ; seuls rôles, entités et DocTypes natifs (+ DocTypes DTP marqués `custom` à confirmer VPS). |
| 8 | VPS pour tous projets | Application des fixtures = VPS (§7), jamais local. |
| — | Séparation des pouvoirs | `set_user_permissions` réservé au RBAC Admin (test). |
**DocTypes `custom: true`** (`Faisabilité`, `Publiciste Log`, `CONFOTUR
Application`, `API Access`) = DocTypes DTP **à créer** — existence **à confirmer
VPS** par l'agent ERPNext avant application (cohérent avec l'interdit « documenter
du code sans vérifier l'existence courante »).
## 7. Application sur VPS (hors périmètre worker)
Ce worker n'écrit **jamais** sur le VPS. L'agent ERPNext Backend appliquera la
cible côté serveur (`erpnext-backend-1`) :
1. Générer les fixtures `Role` + `Custom DocPerm` depuis `rbac_50_roles.json`.
2. `bench --site frontend migrate` pour installer les rôles.
3. Créer les DocTypes DTP `custom` manquants (§6) **après** confirmation.
4. Mapper les `scope_donnees` en `User Permission` par utilisateur.
5. Vérification HTTP post-déploiement (workflow #3) + audit QA 4Big.
> Un **générateur de fixtures** `rbac_50_roles.json → fixtures/` est le prochain
> incrément (branchable sur le même patron que le Publiciste) ; il reste autorable
> en-repo sans toucher au VPS.
## 8. Vérification (en-repo, sans toucher au VPS)
- `python3 -m unittest discover -s tests -v`**10/10 verts** (schéma maison +
oracle `jsonschema`, 50 rôles, unicité, couverture 5 portails, séparation des
pouvoirs).
- `rbac_50_roles.json` : JSON strict valide (couvert par `ci/validate_json.sh`).
- Job CI dédié `rbac-tests` ajouté au **gate** (`.gitea/workflows/ci.yml`,
Gitea Actions uniquement · #2).
## 9. Auto-score 4Big du livrable : **95/100**
_Réserve 5_ : application des fixtures + création des DocTypes `custom` +
mapping `User Permission` = côté VPS (agent ERPNext, hors périmètre worker) ;
plafonds d'approbation monétaires par rôle volontairement **non chiffrés** ici
(anti-invention #6 — à définir avec la Direction sur pièces). Validé statiquement
en-repo (10 tests verts + schéma conforme + gate CI).
+121
View File
@@ -0,0 +1,121 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://oto.dtp/schemas/rbac/rbac.schema.json",
"title": "Contrat RBAC · OTO Enterprise OS DTP (50 rôles)",
"description": "Design machine-lisible des 50 rôles RBAC (CLAUDE.md · roadmap Sprint 2 · ERPNext Backend). Chaque rôle cible un Role natif Frappe v15 + un jeu de permissions par DocType. Les bindings sont la CIBLE à appliquer sur le VPS par l'agent ERPNext (bench/fixtures) — ce document ne touche jamais la prod (contrainte worker).",
"type": "object",
"required": ["version", "generated_at", "cible_rbac_roles", "portails_business", "roles"],
"additionalProperties": false,
"properties": {
"version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
"generated_at": { "type": "string", "format": "date-time" },
"cible_rbac_roles": {
"type": "integer",
"const": 50,
"description": "Cible non-négociable CLAUDE.md « RBAC 50 rôles ». La longueur de roles[] DOIT valoir 50 (contrôlé par le test)."
},
"portails_business": {
"type": "array",
"minItems": 5,
"maxItems": 5,
"uniqueItems": true,
"items": { "type": "string", "enum": ["ventes", "construction", "achat", "compta", "direction"] },
"description": "Les 5 portails rôle métier de la roadmap Sprint 4. « plateforme » est une console technique transversale, hors de ce compte de 5."
},
"roles": {
"type": "array",
"minItems": 50,
"maxItems": 50,
"items": { "$ref": "#/definitions/role" }
}
},
"definitions": {
"role": {
"type": "object",
"required": [
"id", "nom_fr", "famille", "portail", "entite_principale",
"niveau", "erpnext_role_name", "scope_donnees", "description",
"modules", "permissions_cibles"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
"minLength": 3,
"description": "Identifiant kebab-case unique (unicité vérifiée par le test)."
},
"nom_fr": { "type": "string", "minLength": 1 },
"famille": {
"type": "string",
"enum": ["direction", "ventes", "marketing", "construction", "achat", "finance", "faisabilite", "legal", "plateforme"]
},
"portail": {
"type": "string",
"enum": ["ventes", "construction", "achat", "compta", "direction", "plateforme"],
"description": "Console de rattachement. Les 5 premières = portails métier (roadmap S4) ; « plateforme » = console technique transversale."
},
"entite_principale": {
"type": "string",
"enum": ["WAF", "WAG", "WA SRL", "AC Arias Cuevas", "Consortium ECR DR", "Helios RD", "Ploutos", "9060 QC", "Groupe"],
"description": "Entité juridique de rattachement principal (CLAUDE.md §Entités). « Groupe » = périmètre consolidé transversal."
},
"niveau": {
"type": "integer",
"minimum": 1,
"maximum": 5,
"description": "Niveau hiérarchique/sensibilité : 1 externe/opérationnel → 5 direction/système."
},
"erpnext_role_name": {
"type": "string",
"minLength": 4,
"pattern": "^OTO ",
"description": "Nom du DocType Role Frappe v15 à créer (préfixe « OTO » pour ne pas entrer en collision avec les rôles natifs). Unicité vérifiée par le test."
},
"scope_donnees": {
"type": "string",
"enum": ["own", "equipe", "entite", "groupe"],
"description": "Row-level (User Permissions Frappe) : own=ses docs · equipe=son équipe · entite=sa Company · groupe=consolidé."
},
"description": { "type": "string", "minLength": 1 },
"modules": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": { "type": "string", "minLength": 1 },
"description": "Modules/Workspaces ERPNext visibles pour ce rôle."
},
"permissions_cibles": {
"type": "array",
"minItems": 1,
"description": "Bindings CIBLES par DocType (à appliquer sur VPS via fixtures). Verbes = actions de permission Frappe v15.",
"items": {
"type": "object",
"required": ["doctype", "actions"],
"additionalProperties": false,
"properties": {
"doctype": { "type": "string", "minLength": 1 },
"custom": {
"type": "boolean",
"description": "true = DocType OTOV7/DTP à créer (non natif ERPNext) — à confirmer VPS avant application."
},
"actions": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "string",
"enum": [
"read", "write", "create", "delete", "submit", "cancel",
"amend", "print", "email", "export", "import", "report",
"share", "set_user_permissions"
]
}
}
}
}
}
}
}
}
}
+832
View File
@@ -0,0 +1,832 @@
{
"version": "1.0.0",
"generated_at": "2026-07-30T00:00:00Z",
"cible_rbac_roles": 50,
"portails_business": ["ventes", "construction", "achat", "compta", "direction"],
"roles": [
{
"id": "direction-president-waf",
"nom_fr": "Président · WAF (Holding)",
"famille": "direction",
"portail": "direction",
"entite_principale": "WAF",
"niveau": 5,
"erpnext_role_name": "OTO Direction Président",
"scope_donnees": "groupe",
"description": "Vue consolidée toutes entités ; approbations stratégiques et plafonds haut niveau. Lecture large, écriture limitée aux validations.",
"modules": ["Accounts", "CRM", "Selling", "Buying", "Projects", "OTOV7 Faisabilité"],
"permissions_cibles": [
{ "doctype": "Sales Invoice", "actions": ["read", "report", "print", "export"] },
{ "doctype": "Purchase Invoice", "actions": ["read", "report", "export"] },
{ "doctype": "Opportunity", "actions": ["read", "report"] },
{ "doctype": "Faisabilité", "custom": true, "actions": ["read", "report"] }
]
},
{
"id": "direction-dg",
"nom_fr": "Directeur Général",
"famille": "direction",
"portail": "direction",
"entite_principale": "Groupe",
"niveau": 5,
"erpnext_role_name": "OTO Direction Générale",
"scope_donnees": "groupe",
"description": "Pilotage opérationnel du groupe ; approbation devis/commandes au-delà des plafonds directeurs.",
"modules": ["Accounts", "CRM", "Selling", "Buying", "Projects", "HR"],
"permissions_cibles": [
{ "doctype": "Quotation", "actions": ["read", "write", "submit", "cancel", "report"] },
{ "doctype": "Sales Order", "actions": ["read", "write", "submit", "cancel", "report"] },
{ "doctype": "Purchase Order", "actions": ["read", "write", "submit", "cancel", "report"] },
{ "doctype": "Project", "actions": ["read", "write", "report"] }
]
},
{
"id": "direction-cfo",
"nom_fr": "Directeur Financier (CFO)",
"famille": "finance",
"portail": "direction",
"entite_principale": "Groupe",
"niveau": 5,
"erpnext_role_name": "OTO Direction Financière",
"scope_donnees": "groupe",
"description": "Responsable comptabilité/trésorerie consolidées ; validation des écritures et des paiements.",
"modules": ["Accounts", "Buying", "Selling", "Report"],
"permissions_cibles": [
{ "doctype": "Journal Entry", "actions": ["read", "write", "create", "submit", "cancel", "report"] },
{ "doctype": "Payment Entry", "actions": ["read", "write", "submit", "cancel", "report"] },
{ "doctype": "Sales Invoice", "actions": ["read", "write", "submit", "cancel", "report", "export"] },
{ "doctype": "Purchase Invoice", "actions": ["read", "write", "submit", "cancel", "report", "export"] }
]
},
{
"id": "direction-coo",
"nom_fr": "Directeur des Opérations (COO)",
"famille": "direction",
"portail": "direction",
"entite_principale": "Groupe",
"niveau": 4,
"erpnext_role_name": "OTO Direction Opérations",
"scope_donnees": "groupe",
"description": "Coordination construction/achat/logistique multi-projets ; supervision des jalons.",
"modules": ["Projects", "Buying", "Stock", "Report"],
"permissions_cibles": [
{ "doctype": "Project", "actions": ["read", "write", "create", "report"] },
{ "doctype": "Task", "actions": ["read", "write", "create", "report"] },
{ "doctype": "Purchase Order", "actions": ["read", "report"] }
]
},
{
"id": "direction-cco",
"nom_fr": "Directeur Commercial (CCO)",
"famille": "direction",
"portail": "direction",
"entite_principale": "Groupe",
"niveau": 4,
"erpnext_role_name": "OTO Direction Commerciale",
"scope_donnees": "groupe",
"description": "Stratégie commerciale groupe ; supervision pipeline et marketing.",
"modules": ["CRM", "Selling", "Website", "Report"],
"permissions_cibles": [
{ "doctype": "Opportunity", "actions": ["read", "write", "report", "export"] },
{ "doctype": "Quotation", "actions": ["read", "write", "report"] },
{ "doctype": "Lead", "actions": ["read", "report"] }
]
},
{
"id": "direction-board",
"nom_fr": "Conseil d'Administration (lecture consolidée)",
"famille": "direction",
"portail": "direction",
"entite_principale": "Groupe",
"niveau": 5,
"erpnext_role_name": "OTO Conseil Administration",
"scope_donnees": "groupe",
"description": "Accès strictement lecture aux tableaux de bord consolidés et rapports 4Big (aucune écriture).",
"modules": ["Accounts", "Report", "OTOV7 Faisabilité"],
"permissions_cibles": [
{ "doctype": "Sales Invoice", "actions": ["read", "report"] },
{ "doctype": "Faisabilité", "custom": true, "actions": ["read", "report"] }
]
},
{
"id": "ventes-directeur",
"nom_fr": "Directeur des Ventes",
"famille": "ventes",
"portail": "ventes",
"entite_principale": "Helios RD",
"niveau": 4,
"erpnext_role_name": "OTO Ventes Directeur",
"scope_donnees": "entite",
"description": "Pilote le pipeline Helios RD ; approuve devis et remises ; assigne les leads aux équipes.",
"modules": ["CRM", "Selling", "Report"],
"permissions_cibles": [
{ "doctype": "Lead", "actions": ["read", "write", "create", "share", "report"] },
{ "doctype": "Opportunity", "actions": ["read", "write", "create", "report", "export"] },
{ "doctype": "Quotation", "actions": ["read", "write", "create", "submit", "cancel", "report"] },
{ "doctype": "Sales Order", "actions": ["read", "write", "submit", "report"] }
]
},
{
"id": "ventes-chef-equipe",
"nom_fr": "Chef d'Équipe Ventes",
"famille": "ventes",
"portail": "ventes",
"entite_principale": "Helios RD",
"niveau": 3,
"erpnext_role_name": "OTO Ventes Chef Équipe",
"scope_donnees": "equipe",
"description": "Supervise les conseillers de son équipe ; réaffecte leads et suit les objectifs.",
"modules": ["CRM", "Selling"],
"permissions_cibles": [
{ "doctype": "Lead", "actions": ["read", "write", "create", "report"] },
{ "doctype": "Opportunity", "actions": ["read", "write", "create", "report"] },
{ "doctype": "Quotation", "actions": ["read", "write", "create", "submit"] }
]
},
{
"id": "ventes-conseiller",
"nom_fr": "Conseiller Ventes",
"famille": "ventes",
"portail": "ventes",
"entite_principale": "Helios RD",
"niveau": 2,
"erpnext_role_name": "OTO Ventes Conseiller",
"scope_donnees": "own",
"description": "Gère ses propres leads/opportunités et produit des devis (soumis à approbation).",
"modules": ["CRM", "Selling"],
"permissions_cibles": [
{ "doctype": "Lead", "actions": ["read", "write", "create"] },
{ "doctype": "Opportunity", "actions": ["read", "write", "create"] },
{ "doctype": "Quotation", "actions": ["read", "write", "create", "print", "email"] }
]
},
{
"id": "ventes-courtier-externe",
"nom_fr": "Agent Externe / Courtier",
"famille": "ventes",
"portail": "ventes",
"entite_principale": "Helios RD",
"niveau": 1,
"erpnext_role_name": "OTO Ventes Courtier Externe",
"scope_donnees": "own",
"description": "Partenaire externe : soumet des leads et suit ses propres réservations/commissions, sans accès aux données internes.",
"modules": ["CRM"],
"permissions_cibles": [
{ "doctype": "Lead", "actions": ["read", "create"] },
{ "doctype": "Opportunity", "actions": ["read"] }
]
},
{
"id": "ventes-reservations",
"nom_fr": "Coordinateur Réservations",
"famille": "ventes",
"portail": "ventes",
"entite_principale": "Helios RD",
"niveau": 2,
"erpnext_role_name": "OTO Ventes Réservations",
"scope_donnees": "entite",
"description": "Enregistre les réservations/dépôts, gère la disponibilité des unités et l'agenda des visites.",
"modules": ["Selling", "CRM"],
"permissions_cibles": [
{ "doctype": "Sales Order", "actions": ["read", "write", "create", "submit"] },
{ "doctype": "Payment Entry", "actions": ["read", "create"] }
]
},
{
"id": "ventes-contrats",
"nom_fr": "Gestionnaire Contrats de Vente",
"famille": "ventes",
"portail": "ventes",
"entite_principale": "WA SRL",
"niveau": 3,
"erpnext_role_name": "OTO Ventes Contrats",
"scope_donnees": "entite",
"description": "Établit et suit les contrats (promesse → contrat définitif) ; assure la cohérence avec le devis validé.",
"modules": ["Selling", "Accounts"],
"permissions_cibles": [
{ "doctype": "Sales Order", "actions": ["read", "write", "submit", "print", "email"] },
{ "doctype": "Sales Invoice", "actions": ["read", "create", "print"] }
]
},
{
"id": "ventes-confotur",
"nom_fr": "Coordinateur CONFOTUR (Ventes)",
"famille": "ventes",
"portail": "ventes",
"entite_principale": "WA SRL",
"niveau": 3,
"erpnext_role_name": "OTO Ventes CONFOTUR",
"scope_donnees": "entite",
"description": "Monte les dossiers d'incitation CONFOTUR côté vente (pièces client, éligibilité) ; liaison avec l'agent ONAPI/Legal.",
"modules": ["Selling", "OTOV7 CONFOTUR"],
"permissions_cibles": [
{ "doctype": "CONFOTUR Application", "custom": true, "actions": ["read", "write", "create", "print"] },
{ "doctype": "Customer", "actions": ["read"] }
]
},
{
"id": "ventes-apres-vente",
"nom_fr": "Support Après-Vente",
"famille": "ventes",
"portail": "ventes",
"entite_principale": "Helios RD",
"niveau": 2,
"erpnext_role_name": "OTO Ventes Après-Vente",
"scope_donnees": "entite",
"description": "Traite les demandes clients post-signature (livraison, garanties) via les tickets et les tâches.",
"modules": ["CRM", "Support", "Projects"],
"permissions_cibles": [
{ "doctype": "Issue", "actions": ["read", "write", "create"] },
{ "doctype": "Customer", "actions": ["read"] }
]
},
{
"id": "marketing-directeur",
"nom_fr": "Directeur Marketing",
"famille": "marketing",
"portail": "ventes",
"entite_principale": "Helios RD",
"niveau": 4,
"erpnext_role_name": "OTO Marketing Directeur",
"scope_donnees": "entite",
"description": "Pilote la marque publique Helios RD, les campagnes et la validation du contenu du site vente.otov7.com.",
"modules": ["CRM", "Website", "Report"],
"permissions_cibles": [
{ "doctype": "Web Page", "actions": ["read", "write", "create"] },
{ "doctype": "Publiciste Log", "custom": true, "actions": ["read", "report"] }
]
},
{
"id": "marketing-publiciste",
"nom_fr": "Éditeur Contenu / Publiciste",
"famille": "marketing",
"portail": "ventes",
"entite_principale": "Helios RD",
"niveau": 2,
"erpnext_role_name": "OTO Marketing Publiciste",
"scope_donnees": "entite",
"description": "Compte applicatif de l'agent Publiciste : publie le site public à partir des faisabilités validées (jamais d'invention de prix — CLAUDE.md #6).",
"modules": ["Website", "OTOV7 Publiciste"],
"permissions_cibles": [
{ "doctype": "Web Page", "actions": ["read", "write", "create"] },
{ "doctype": "Publiciste Log", "custom": true, "actions": ["read", "write", "create"] }
]
},
{
"id": "marketing-seo",
"nom_fr": "Spécialiste SEO",
"famille": "marketing",
"portail": "ventes",
"entite_principale": "Helios RD",
"niveau": 2,
"erpnext_role_name": "OTO Marketing SEO",
"scope_donnees": "entite",
"description": "Optimise l'indexation trilingue FR/EN/ES (hreflang, schema.org) ; suit Google Search Console.",
"modules": ["Website", "Report"],
"permissions_cibles": [
{ "doctype": "Web Page", "actions": ["read", "write"] }
]
},
{
"id": "marketing-social",
"nom_fr": "Community / Réseaux Sociaux",
"famille": "marketing",
"portail": "ventes",
"entite_principale": "Helios RD",
"niveau": 1,
"erpnext_role_name": "OTO Marketing Social",
"scope_donnees": "entite",
"description": "Gère les publications réseaux sociaux et remonte les leads sociaux dans le CRM.",
"modules": ["CRM", "Website"],
"permissions_cibles": [
{ "doctype": "Lead", "actions": ["read", "create"] }
]
},
{
"id": "construction-directeur",
"nom_fr": "Directeur Construction",
"famille": "construction",
"portail": "construction",
"entite_principale": "AC Arias Cuevas",
"niveau": 4,
"erpnext_role_name": "OTO Construction Directeur",
"scope_donnees": "entite",
"description": "Dirige AC Arias Cuevas ; approuve les projets, budgets travaux et jalons de chantier.",
"modules": ["Projects", "Buying", "Stock", "Report"],
"permissions_cibles": [
{ "doctype": "Project", "actions": ["read", "write", "create", "submit", "report"] },
{ "doctype": "Task", "actions": ["read", "write", "create", "report"] },
{ "doctype": "Purchase Order", "actions": ["read", "write", "submit"] }
]
},
{
"id": "construction-chef-projet",
"nom_fr": "Chef de Projet Construction",
"famille": "construction",
"portail": "construction",
"entite_principale": "AC Arias Cuevas",
"niveau": 3,
"erpnext_role_name": "OTO Construction Chef Projet",
"scope_donnees": "equipe",
"description": "Pilote un projet : planning, tâches, avancement et demandes d'achat de chantier.",
"modules": ["Projects", "Buying"],
"permissions_cibles": [
{ "doctype": "Project", "actions": ["read", "write", "report"] },
{ "doctype": "Task", "actions": ["read", "write", "create"] },
{ "doctype": "Material Request", "actions": ["read", "write", "create", "submit"] }
]
},
{
"id": "construction-ingenieur",
"nom_fr": "Ingénieur de Chantier",
"famille": "construction",
"portail": "construction",
"entite_principale": "AC Arias Cuevas",
"niveau": 2,
"erpnext_role_name": "OTO Construction Ingénieur",
"scope_donnees": "equipe",
"description": "Suit l'exécution technique sur site ; met à jour l'avancement des tâches et les feuilles de temps.",
"modules": ["Projects"],
"permissions_cibles": [
{ "doctype": "Task", "actions": ["read", "write"] },
{ "doctype": "Timesheet", "actions": ["read", "write", "create"] }
]
},
{
"id": "construction-architecte",
"nom_fr": "Architecte",
"famille": "construction",
"portail": "construction",
"entite_principale": "AC Arias Cuevas",
"niveau": 3,
"erpnext_role_name": "OTO Construction Architecte",
"scope_donnees": "entite",
"description": "Produit le volet Architecture des faisabilités ; valide les plans et les modèles IFC.",
"modules": ["Projects", "OTOV7 Faisabilité"],
"permissions_cibles": [
{ "doctype": "Faisabilité", "custom": true, "actions": ["read", "write", "create"] },
{ "doctype": "Project", "actions": ["read"] }
]
},
{
"id": "construction-qaqc",
"nom_fr": "Contrôleur Qualité Chantier (QA/QC)",
"famille": "construction",
"portail": "construction",
"entite_principale": "AC Arias Cuevas",
"niveau": 2,
"erpnext_role_name": "OTO Construction QAQC",
"scope_donnees": "entite",
"description": "Contrôle la conformité qualité du chantier ; consigne inspections et non-conformités.",
"modules": ["Projects", "Quality"],
"permissions_cibles": [
{ "doctype": "Quality Inspection", "actions": ["read", "write", "create", "submit"] },
{ "doctype": "Task", "actions": ["read"] }
]
},
{
"id": "construction-bim",
"nom_fr": "Coordinateur BIM",
"famille": "construction",
"portail": "construction",
"entite_principale": "AC Arias Cuevas",
"niveau": 3,
"erpnext_role_name": "OTO Construction BIM",
"scope_donnees": "entite",
"description": "Coordonne les maquettes BIM (Blender/Bonsai/IFC/Speckle) ; publie les modèles vers bim-cloud.otov7.com.",
"modules": ["Projects", "OTOV7 Faisabilité"],
"permissions_cibles": [
{ "doctype": "Faisabilité", "custom": true, "actions": ["read", "write"] },
{ "doctype": "File", "actions": ["read", "write", "create"] }
]
},
{
"id": "construction-sous-traitants",
"nom_fr": "Superviseur Sous-traitants",
"famille": "construction",
"portail": "construction",
"entite_principale": "AC Arias Cuevas",
"niveau": 2,
"erpnext_role_name": "OTO Construction Sous-traitants",
"scope_donnees": "equipe",
"description": "Suit les sous-traitants et leurs livrables ; valide l'avancement pour paiement.",
"modules": ["Projects", "Buying"],
"permissions_cibles": [
{ "doctype": "Purchase Order", "actions": ["read", "report"] },
{ "doctype": "Task", "actions": ["read", "write"] }
]
},
{
"id": "achat-directeur",
"nom_fr": "Directeur des Achats",
"famille": "achat",
"portail": "achat",
"entite_principale": "WA SRL",
"niveau": 4,
"erpnext_role_name": "OTO Achat Directeur",
"scope_donnees": "entite",
"description": "Pilote la fonction achats ; approuve commandes fournisseurs au-delà des plafonds acheteurs.",
"modules": ["Buying", "Stock", "Accounts", "Report"],
"permissions_cibles": [
{ "doctype": "Purchase Order", "actions": ["read", "write", "create", "submit", "cancel", "report"] },
{ "doctype": "Supplier", "actions": ["read", "write", "create"] },
{ "doctype": "Material Request", "actions": ["read", "write", "submit"] }
]
},
{
"id": "achat-acheteur",
"nom_fr": "Acheteur / Approvisionneur",
"famille": "achat",
"portail": "achat",
"entite_principale": "WA SRL",
"niveau": 2,
"erpnext_role_name": "OTO Achat Acheteur",
"scope_donnees": "entite",
"description": "Émet demandes de prix et commandes fournisseurs (soumises à approbation) ; suit les délais.",
"modules": ["Buying", "Stock"],
"permissions_cibles": [
{ "doctype": "Material Request", "actions": ["read", "write", "create"] },
{ "doctype": "Request for Quotation", "actions": ["read", "write", "create", "submit"] },
{ "doctype": "Purchase Order", "actions": ["read", "write", "create"] }
]
},
{
"id": "achat-fournisseurs",
"nom_fr": "Gestionnaire Fournisseurs",
"famille": "achat",
"portail": "achat",
"entite_principale": "WA SRL",
"niveau": 2,
"erpnext_role_name": "OTO Achat Fournisseurs",
"scope_donnees": "entite",
"description": "Tient à jour la base fournisseurs, les conditions et la conformité documentaire.",
"modules": ["Buying"],
"permissions_cibles": [
{ "doctype": "Supplier", "actions": ["read", "write", "create"] },
{ "doctype": "Contact", "actions": ["read", "write", "create"] }
]
},
{
"id": "achat-magasinier",
"nom_fr": "Magasinier / Inventaire",
"famille": "achat",
"portail": "achat",
"entite_principale": "AC Arias Cuevas",
"niveau": 2,
"erpnext_role_name": "OTO Achat Magasinier",
"scope_donnees": "entite",
"description": "Gère les stocks de chantier/dépôt : entrées, sorties et inventaires.",
"modules": ["Stock"],
"permissions_cibles": [
{ "doctype": "Stock Entry", "actions": ["read", "write", "create", "submit"] },
{ "doctype": "Item", "actions": ["read"] }
]
},
{
"id": "achat-reception",
"nom_fr": "Contrôleur Réception Matériaux",
"famille": "achat",
"portail": "achat",
"entite_principale": "AC Arias Cuevas",
"niveau": 2,
"erpnext_role_name": "OTO Achat Réception",
"scope_donnees": "entite",
"description": "Réceptionne et contrôle les livraisons ; établit les bons de réception.",
"modules": ["Stock", "Buying"],
"permissions_cibles": [
{ "doctype": "Purchase Receipt", "actions": ["read", "write", "create", "submit"] },
{ "doctype": "Purchase Order", "actions": ["read"] }
]
},
{
"id": "compta-controleur-gestion",
"nom_fr": "Contrôleur de Gestion",
"famille": "finance",
"portail": "compta",
"entite_principale": "Groupe",
"niveau": 4,
"erpnext_role_name": "OTO Compta Contrôle Gestion",
"scope_donnees": "groupe",
"description": "Suit budgets, marges et point d'équilibre (52% pré-vente) ; produit les rapports de gestion consolidés.",
"modules": ["Accounts", "Report"],
"permissions_cibles": [
{ "doctype": "Budget", "actions": ["read", "write", "create", "report"] },
{ "doctype": "GL Entry", "actions": ["read", "report", "export"] },
{ "doctype": "Cost Center", "actions": ["read", "report"] }
]
},
{
"id": "compta-comptable-general",
"nom_fr": "Comptable Général",
"famille": "finance",
"portail": "compta",
"entite_principale": "WA SRL",
"niveau": 3,
"erpnext_role_name": "OTO Compta Général",
"scope_donnees": "entite",
"description": "Tient la comptabilité générale de l'entité ; saisit et rapproche les écritures.",
"modules": ["Accounts"],
"permissions_cibles": [
{ "doctype": "Journal Entry", "actions": ["read", "write", "create", "submit"] },
{ "doctype": "Account", "actions": ["read"] }
]
},
{
"id": "compta-fournisseurs-ap",
"nom_fr": "Comptable Fournisseurs (AP)",
"famille": "finance",
"portail": "compta",
"entite_principale": "WA SRL",
"niveau": 2,
"erpnext_role_name": "OTO Compta Fournisseurs AP",
"scope_donnees": "entite",
"description": "Traite les factures fournisseurs et prépare les paiements (soumis à approbation trésorier/CFO).",
"modules": ["Accounts", "Buying"],
"permissions_cibles": [
{ "doctype": "Purchase Invoice", "actions": ["read", "write", "create", "submit"] },
{ "doctype": "Payment Entry", "actions": ["read", "create"] }
]
},
{
"id": "compta-clients-ar",
"nom_fr": "Comptable Clients (AR)",
"famille": "finance",
"portail": "compta",
"entite_principale": "Helios RD",
"niveau": 2,
"erpnext_role_name": "OTO Compta Clients AR",
"scope_donnees": "entite",
"description": "Émet les factures clients et suit les encaissements (Cardnet · USD/DOP) et relances.",
"modules": ["Accounts", "Selling"],
"permissions_cibles": [
{ "doctype": "Sales Invoice", "actions": ["read", "write", "create", "submit"] },
{ "doctype": "Payment Entry", "actions": ["read", "create"] }
]
},
{
"id": "compta-tresorier",
"nom_fr": "Trésorier · Ploutos",
"famille": "finance",
"portail": "compta",
"entite_principale": "Ploutos",
"niveau": 3,
"erpnext_role_name": "OTO Compta Trésorier",
"scope_donnees": "entite",
"description": "Gère la trésorerie et le patrimoine monétaire (Ploutos) ; valide les décaissements.",
"modules": ["Accounts"],
"permissions_cibles": [
{ "doctype": "Payment Entry", "actions": ["read", "write", "submit", "cancel"] },
{ "doctype": "Bank Transaction", "actions": ["read", "write", "submit"] }
]
},
{
"id": "compta-paie",
"nom_fr": "Gestionnaire Paie · Consortium ECR DR",
"famille": "finance",
"portail": "compta",
"entite_principale": "Consortium ECR DR",
"niveau": 3,
"erpnext_role_name": "OTO Compta Paie",
"scope_donnees": "entite",
"description": "Traite la paie (paymaster RH Consortium ECR DR) ; établit et soumet les bulletins.",
"modules": ["Payroll", "HR"],
"permissions_cibles": [
{ "doctype": "Salary Slip", "actions": ["read", "write", "create", "submit"] },
{ "doctype": "Employee", "actions": ["read"] }
]
},
{
"id": "compta-fiscaliste-ecf",
"nom_fr": "Fiscaliste / e-CF DGII",
"famille": "finance",
"portail": "compta",
"entite_principale": "WA SRL",
"niveau": 3,
"erpnext_role_name": "OTO Compta Fiscaliste eCF",
"scope_donnees": "entite",
"description": "Gère la facturation électronique e-CF (Compupar/DGII) et la conformité fiscale RD.",
"modules": ["Accounts", "Report"],
"permissions_cibles": [
{ "doctype": "Sales Invoice", "actions": ["read", "write", "submit", "export"] },
{ "doctype": "Purchase Invoice", "actions": ["read", "export"] }
]
},
{
"id": "compta-audit-uaf",
"nom_fr": "Auditeur Interne / Conformité UAF",
"famille": "finance",
"portail": "compta",
"entite_principale": "Groupe",
"niveau": 4,
"erpnext_role_name": "OTO Compta Audit UAF",
"scope_donnees": "groupe",
"description": "Audit interne et conformité anti-blanchiment (UAF) ; accès lecture/rapport étendu, aucune écriture comptable.",
"modules": ["Accounts", "Report"],
"permissions_cibles": [
{ "doctype": "GL Entry", "actions": ["read", "report", "export"] },
{ "doctype": "Payment Entry", "actions": ["read", "report"] },
{ "doctype": "Sales Invoice", "actions": ["read", "report"] }
]
},
{
"id": "faisabilite-analyste",
"nom_fr": "Analyste Faisabilité",
"famille": "faisabilite",
"portail": "direction",
"entite_principale": "WA SRL",
"niveau": 3,
"erpnext_role_name": "OTO Faisabilité Analyste",
"scope_donnees": "entite",
"description": "Produit les faisabilités 4 volets (Masterplan/Architecture/Paysage/Ingénierie) niveau 4Big ; versionne et score.",
"modules": ["OTOV7 Faisabilité", "Projects", "Report"],
"permissions_cibles": [
{ "doctype": "Faisabilité", "custom": true, "actions": ["read", "write", "create", "submit", "report"] },
{ "doctype": "Project", "actions": ["read"] }
]
},
{
"id": "faisabilite-rendu-3d",
"nom_fr": "Spécialiste Rendu 3D",
"famille": "faisabilite",
"portail": "construction",
"entite_principale": "WA SRL",
"niveau": 2,
"erpnext_role_name": "OTO Faisabilité Rendu 3D",
"scope_donnees": "entite",
"description": "Génère les rendus Flux liés au projet réel (❌ IA générique interdite — CLAUDE.md) ; 6 vues/projet.",
"modules": ["OTOV7 Faisabilité"],
"permissions_cibles": [
{ "doctype": "File", "actions": ["read", "write", "create"] },
{ "doctype": "Faisabilité", "custom": true, "actions": ["read"] }
]
},
{
"id": "faisabilite-ifc-speckle",
"nom_fr": "Gestionnaire IFC / Speckle",
"famille": "faisabilite",
"portail": "construction",
"entite_principale": "WA SRL",
"niveau": 2,
"erpnext_role_name": "OTO Faisabilité IFC Speckle",
"scope_donnees": "entite",
"description": "Exporte IFC→GLB et publie les modèles sur bim-cloud.otov7.com pour le viewer console.",
"modules": ["OTOV7 Faisabilité"],
"permissions_cibles": [
{ "doctype": "File", "actions": ["read", "write", "create"] },
{ "doctype": "Faisabilité", "custom": true, "actions": ["read", "write"] }
]
},
{
"id": "faisabilite-economiste",
"nom_fr": "Économiste de la Construction (métrés)",
"famille": "faisabilite",
"portail": "construction",
"entite_principale": "AC Arias Cuevas",
"niveau": 3,
"erpnext_role_name": "OTO Faisabilité Économiste",
"scope_donnees": "entite",
"description": "Produit métrés et quantitatifs (BIM compras) pour le volet Ingénierie ; chiffre les coûts travaux.",
"modules": ["OTOV7 Faisabilité", "Buying", "Stock"],
"permissions_cibles": [
{ "doctype": "Faisabilité", "custom": true, "actions": ["read", "write"] },
{ "doctype": "Item", "actions": ["read"] }
]
},
{
"id": "legal-directeur",
"nom_fr": "Directeur Juridique",
"famille": "legal",
"portail": "direction",
"entite_principale": "WAF",
"niveau": 4,
"erpnext_role_name": "OTO Legal Directeur",
"scope_donnees": "groupe",
"description": "Supervise les contrats, la conformité et les dépôts légaux du groupe ; valide les documents à portée juridique.",
"modules": ["OTOV7 CONFOTUR", "Accounts", "Report"],
"permissions_cibles": [
{ "doctype": "CONFOTUR Application", "custom": true, "actions": ["read", "write", "submit", "report"] },
{ "doctype": "Contract", "actions": ["read", "write", "create", "submit"] }
]
},
{
"id": "legal-onapi",
"nom_fr": "Agent ONAPI / Propriété Intellectuelle",
"famille": "legal",
"portail": "direction",
"entite_principale": "WAF",
"niveau": 2,
"erpnext_role_name": "OTO Legal ONAPI",
"scope_donnees": "groupe",
"description": "Prépare et suit les dépôts ONAPI (marques, Classes 36/37/43) et les dossiers CONFOTUR (P05/P07).",
"modules": ["OTOV7 CONFOTUR"],
"permissions_cibles": [
{ "doctype": "CONFOTUR Application", "custom": true, "actions": ["read", "write", "create"] }
]
},
{
"id": "plateforme-devops",
"nom_fr": "Administrateur Système (DevOps)",
"famille": "plateforme",
"portail": "plateforme",
"entite_principale": "9060 QC",
"niveau": 5,
"erpnext_role_name": "OTO Plateforme DevOps",
"scope_donnees": "groupe",
"description": "Administre l'infrastructure (Docker, Gitea, systemd, nginx) et les déploiements. Aucune plateforme git hors Gitea (CLAUDE.md #2).",
"modules": ["Core", "Website", "Report"],
"permissions_cibles": [
{ "doctype": "Scheduled Job Type", "actions": ["read", "write"] },
{ "doctype": "Server Script", "actions": ["read", "write", "create"] }
]
},
{
"id": "plateforme-rbac-admin",
"nom_fr": "Administrateur RBAC / Sécurité",
"famille": "plateforme",
"portail": "plateforme",
"entite_principale": "9060 QC",
"niveau": 5,
"erpnext_role_name": "OTO Plateforme RBAC Admin",
"scope_donnees": "groupe",
"description": "Gère utilisateurs, rôles et User Permissions ; seul habilité à modifier les habilitations (séparation des pouvoirs).",
"modules": ["Users and Permissions", "Core"],
"permissions_cibles": [
{ "doctype": "User", "actions": ["read", "write", "create", "set_user_permissions"] },
{ "doctype": "Role", "actions": ["read", "write", "create"] },
{ "doctype": "Role Profile", "actions": ["read", "write", "create"] },
{ "doctype": "User Permission", "actions": ["read", "write", "create", "delete"] }
]
},
{
"id": "plateforme-qa",
"nom_fr": "Ingénieur QA Plateforme",
"famille": "plateforme",
"portail": "plateforme",
"entite_principale": "9060 QC",
"niveau": 3,
"erpnext_role_name": "OTO Plateforme QA",
"scope_donnees": "groupe",
"description": "Exécute les audits qualité 4Big (Playwright, night-audit) ; accès lecture large + rapports, aucune écriture métier.",
"modules": ["Report", "Core"],
"permissions_cibles": [
{ "doctype": "Report", "actions": ["read", "report", "export"] },
{ "doctype": "Error Log", "actions": ["read"] }
]
},
{
"id": "plateforme-otoia",
"nom_fr": "Orchestrateur OTOIA (compte système)",
"famille": "plateforme",
"portail": "plateforme",
"entite_principale": "9060 QC",
"niveau": 4,
"erpnext_role_name": "OTO Plateforme OTOIA",
"scope_donnees": "groupe",
"description": "Compte de service de l'agent OTOIA (AEC + RAG + prompt engine). Écrit faisabilités et logs via API ; périmètre limité aux DocTypes DTP.",
"modules": ["OTOV7 Faisabilité", "OTOV7 Publiciste", "Core"],
"permissions_cibles": [
{ "doctype": "Faisabilité", "custom": true, "actions": ["read", "write", "create"] },
{ "doctype": "Publiciste Log", "custom": true, "actions": ["read", "write", "create"] }
]
},
{
"id": "plateforme-mobile",
"nom_fr": "Développeur Mobile",
"famille": "plateforme",
"portail": "plateforme",
"entite_principale": "9060 QC",
"niveau": 2,
"erpnext_role_name": "OTO Plateforme Mobile",
"scope_donnees": "groupe",
"description": "Maintient l'app Expo/React Native et l'API mobile ; gère les builds EAS et les soumissions stores.",
"modules": ["Core", "Website"],
"permissions_cibles": [
{ "doctype": "API Access", "custom": true, "actions": ["read", "write"] }
]
},
{
"id": "plateforme-bi",
"nom_fr": "Analyste Données / BI",
"famille": "plateforme",
"portail": "plateforme",
"entite_principale": "Groupe",
"niveau": 3,
"erpnext_role_name": "OTO Plateforme BI",
"scope_donnees": "groupe",
"description": "Construit tableaux de bord et rapports consolidés (lecture seule) pour la direction ; aucune écriture transactionnelle.",
"modules": ["Report", "Accounts", "CRM"],
"permissions_cibles": [
{ "doctype": "Dashboard", "actions": ["read", "write", "create"] },
{ "doctype": "Report", "actions": ["read", "write", "create", "export"] }
]
}
]
}
+116
View File
@@ -0,0 +1,116 @@
"""Tests RBAC 50 rôles — stdlib pur (unittest), zéro dépendance pip.
Réutilise le validateur JSON-Schema du module Publiciste (Sprint 2) plutôt que
d'en dupliquer un (CLAUDE.md · workflow #5 « éliminer le vieux / ne pas
accumuler de doublons »). L'oracle `jsonschema` est utilisé s'il est présent.
Invariants vérifiés :
1. `rbac_50_roles.json` valide contre `rbac.schema.json`.
2. EXACTEMENT 50 rôles (cible non-négociable CLAUDE.md « RBAC 50 rôles »).
3. `id` et `erpnext_role_name` uniques (pas de collision de rôle Frappe).
4. Les 5 portails métier de la roadmap S4 sont tous couverts par ≥1 rôle.
5. Cohérence interne (portail déclaré ⊆ portails connus, cible=50).
6. Anti-invention (#6) : aucun rôle « own/equipe » n'a le pouvoir
`set_user_permissions` (élévation de privilège) — réservé au RBAC Admin.
"""
import json
import os
import unittest
# --- localisation des fichiers -------------------------------------------------
HERE = os.path.dirname(os.path.abspath(__file__))
RBAC_DIR = os.path.dirname(HERE)
DELIVERABLES = os.path.dirname(RBAC_DIR)
DATA_PATH = os.path.join(RBAC_DIR, "rbac_50_roles.json")
SCHEMA_PATH = os.path.join(RBAC_DIR, "rbac.schema.json")
# --- réutilisation du validateur Publiciste (pas de duplication) ---------------
import sys
sys.path.insert(0, os.path.join(DELIVERABLES, "publiciste"))
from lib import validator as maison # noqa: E402
def _load(path):
with open(path, encoding="utf-8") as fh:
return json.load(fh)
class RbacContractTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.data = _load(DATA_PATH)
cls.schema = _load(SCHEMA_PATH)
cls.roles = cls.data["roles"]
# 1 · conformité au schéma (validateur maison)
def test_valide_contre_schema_maison(self):
errors = maison.validate(self.data, self.schema)
self.assertEqual(errors, [], f"Erreurs de schéma (maison) : {errors}")
# 1bis · oracle jsonschema si disponible
def test_valide_contre_oracle_jsonschema_si_present(self):
try:
import jsonschema
except ImportError:
self.skipTest("jsonschema non installé (validateur maison fait foi)")
jsonschema.validate(self.data, self.schema)
# 2 · cible non-négociable = 50
def test_exactement_50_roles(self):
self.assertEqual(self.data["cible_rbac_roles"], 50)
self.assertEqual(len(self.roles), 50, "La cible CLAUDE.md « RBAC 50 rôles » exige exactement 50 rôles.")
# 3 · unicité des identifiants et des noms de rôle Frappe
def test_ids_uniques(self):
ids = [r["id"] for r in self.roles]
self.assertEqual(len(ids), len(set(ids)), "id de rôle dupliqué.")
def test_noms_erpnext_uniques(self):
names = [r["erpnext_role_name"] for r in self.roles]
self.assertEqual(len(names), len(set(names)), "erpnext_role_name dupliqué (collision Frappe).")
def test_noms_erpnext_prefixes_oto(self):
for r in self.roles:
self.assertTrue(
r["erpnext_role_name"].startswith("OTO "),
f"{r['id']}: le rôle Frappe doit être préfixé « OTO » pour éviter la collision avec les rôles natifs.",
)
# 4 · les 5 portails métier de la roadmap S4 sont tous couverts
def test_cinq_portails_business_couverts(self):
portails_declares = set(self.data["portails_business"])
self.assertEqual(portails_declares, {"ventes", "construction", "achat", "compta", "direction"})
portails_utilises = {r["portail"] for r in self.roles}
for p in portails_declares:
self.assertIn(p, portails_utilises, f"Portail métier « {p} » sans aucun rôle rattaché.")
# 5 · cohérence portail
def test_portail_connu(self):
connus = {"ventes", "construction", "achat", "compta", "direction", "plateforme"}
for r in self.roles:
self.assertIn(r["portail"], connus, f"{r['id']}: portail inconnu {r['portail']!r}")
# 6 · anti-élévation de privilège : set_user_permissions réservé au groupe
def test_set_user_permissions_reserve_admin(self):
for r in self.roles:
verbs = {a for p in r["permissions_cibles"] for a in p["actions"]}
if "set_user_permissions" in verbs:
self.assertEqual(
r["scope_donnees"], "groupe",
f"{r['id']}: 'set_user_permissions' exige un scope 'groupe' (séparation des pouvoirs).",
)
self.assertEqual(
r["famille"], "plateforme",
f"{r['id']}: seul un rôle 'plateforme' peut porter 'set_user_permissions'.",
)
# 7 · chaque rôle a au moins un binding de permission
def test_chaque_role_a_des_permissions(self):
for r in self.roles:
self.assertGreaterEqual(len(r["permissions_cibles"]), 1, f"{r['id']}: aucun binding de permission.")
if __name__ == "__main__":
unittest.main(verbosity=2)