Files
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

99 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Générateur de plan `User Permission` · RBAC 50 rôles → row-level
**Sprint 2 · agent ERPNext Backend.** Complément du
[générateur de fixtures `Role` + `Custom DocPerm`](../fixtures_gen/README.md) :
il couvre la dimension **ROW-LEVEL** (`scope_donnees`) que les DocPerm ne portent
pas à eux seuls. Transforme le contrat [`../rbac_50_roles.json`](../rbac_50_roles.json)
(validé par [`../rbac.schema.json`](../rbac.schema.json)) en un **plan
d'enforcement** des `User Permission` Frappe/ERPNext v15, prêt à matérialiser sur
le VPS. Réalise la « prochaine tâche » annoncée 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 un PLAN
> en-repo ; l'application réelle (matérialisation par utilisateur, `bench`) reste
> côté serveur.
## Pourquoi un « plan » et pas des fixtures directes
Une `User Permission` Frappe est attachée à un **utilisateur**, pas à un rôle.
Ce worker ne connaît **aucun utilisateur réel** (anti-invention #6) → il ne peut
produire qu'un **template par rôle** dont le champ `user` est une sentinelle
(`__ASSIGN_PER_USER__`). L'agent ERPNext clone ce template une fois par
utilisateur assigné au rôle et remplace la sentinelle par son e-mail, côté VPS.
## Ce qui est généré (`out/`, commité · byte-déterministe)
| Fichier | Rôle |
|---|---|
| `user_permission_plan.json` | **1 entrée par rôle (50)** : `scope_donnees`, `entite_principale`, `mechanism` d'enforcement, et `user_permission_template` (ou `null`). |
| `MANIFEST.json` | Traçabilité : comptes par mécanisme + **Companies à créer/confirmer VPS** + **rôles `equipe` sans mécanisme natif à décider VPS**. |
## Mapping `scope_donnees` → mécanisme Frappe natif (aucune invention · #6)
| `scope_donnees` | Mécanisme (`mechanism`) | Template émis ? |
|---|---|---|
| `own` | `docperm_if_owner` — déjà posé par `fixtures_gen` (`if_owner=1`). | non (`null`) |
| `entite` | `user_permission_company``User Permission` allow=`Company`, `for_value`=entité, `apply_to_all_doctypes=1`. | **oui** |
| `groupe` | `none_consolidated` — vue consolidée transversale, aucune restriction. | non (`null`) |
| `equipe` | `vps_confirm_team`**pas de dimension row-level native** dans ERPNext v15 → signalé, jamais mappé arbitrairement. | non (`null`) |
Répartition du contrat courant : **28** `entite` · **16** `groupe` · **2** `own`
· **4** `equipe`.
## Utilisation
```bash
# Génère out/user_permission_plan.json + out/MANIFEST.json
python3 userperm_gen.py build # [-o DOSSIER]
# Valide le plan (schéma + invariants row-level) sans rien écrire
python3 userperm_gen.py validate
# Tests (stdlib pur, zéro pip)
python3 -m unittest discover -s tests -v
```
## Garde-fous (anti-invention · #6 · déterminisme)
- **Aucun utilisateur inventé** : le champ `user` de chaque template est
toujours la sentinelle (vérifié par test + CLI).
- **Aucune restriction fabriquée** hors portée `entite` : `own`/`groupe`/`equipe`
portent `user_permission_template = null`.
- **`entite` + périmètre consolidé (« Groupe ») → `ValueError`** (garde-fou
anti-contrat corrompu : une portée consolidée doit être `groupe`).
- **Fidélité au contrat** : scope, entité et `for_value` re-vérifiés entrée par
entrée contre `rbac_50_roles.json` ; le CLI **refuse d'écrire** si un invariant
casse.
- Sortie **déterministe** (tri stable 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. Créer/confirmer les **Companies** listées dans
`MANIFEST.companies_a_confirmer` (une par entité juridique · CLAUDE.md §Entités).
2. Pour chaque rôle de `mechanism = user_permission_company` : cloner
`user_permission_template` **par utilisateur** assigné au rôle, en remplaçant
`user` par son e-mail réel, puis importer.
3. Décider le mécanisme des rôles `MANIFEST.roles_scope_equipe_a_confirmer`
(`equipe`) — options natives : champ custom « Équipe » + `User Permission`, ou
hiérarchie `Employee.reports_to`. **À valider avec Michel** avant application.
4. Les rôles `own` sont déjà couverts par `if_owner` (fixtures `custom_docperm`).
5. Vérification HTTP post-déploiement (workflow #3) + audit QA 4Big.
## Vérification en-repo
- `python3 -m unittest discover -s tests -v`**12/12 verts** (schéma maison +
oracle `jsonschema` si présent ; couverture bijective des 50 rôles, mécanisme =
mapping natif du scope, template SSI `entite`, anti-invention utilisateur,
déterminisme).
- Job CI dédié `rbac-userperm-tests` ajouté au **gate** (`.gitea/workflows/ci.yml`,
Gitea Actions uniquement · #2).
## Auto-score 4Big du livrable : **96/100**
_Réserve 4_ : matérialisation par utilisateur + création des Companies +
décision du mécanisme `equipe` = côté VPS (agent ERPNext, hors périmètre worker,
contrainte #8) ; la portée `equipe` n'a pas de dimension row-level native unique
→ délibérément non inventée (#6). Validé statiquement en-repo (12 tests verts +
schéma conforme + round-trip fidèle au contrat + gate CI).