```
→ Chaque carte a un attribut **`data-app=""`** que le JavaScript utilise pour la matcher avec la matrice RBAC.
---
## 📄 JavaScript RBAC (à la fin de index.html)
```html
```
---
## 🎭 Création des 8 rôles dans Zitadel
### Étape 1 — Aller dans le project
Console Zitadel → Projects → **Infra Seize** → Roles → New
### Étape 2 — Créer un par un
| Key | Display Name | Group |
|---|---|---|
| `direction` | Direction | hierarchie |
| `manager` | Manager | hierarchie |
| `expert` | Expert | hierarchie |
| `consultant_senior` | Consultant Senior | hierarchie |
| `consultant_junior` | Consultant Junior | hierarchie |
| `alternant` | Alternant | hierarchie |
| `stagiaire` | Stagiaire | hierarchie |
| `support` | Support | hierarchie |
### Étape 3 — Activer "Return user roles during authentication"
Console Zitadel → Projects → **Infra Seize** → General → Settings :
- ☑️ **Return user roles during authentication**
- ❌ **Only authorized users can authenticate** (à laisser DÉCOCHÉ — cf. [D9](../DECISIONS.md))
- ❌ **Authentication restricted to authorized orgs**
### Étape 4 — Configurer chaque App pour transmettre les rôles
Pour chaque application (Intranet, n8n, Portainer, etc.) :
Console Zitadel → Projects → Infra Seize → Applications → `` → Token Settings :
- Auth Token Type : **JWT** (pas Bearer Token)
- ☑️ User roles inside ID Token
- ☑️ Include user's profile info in the ID Token
- ☑️ Add user roles to the access token
**Save**.
---
## 📊 Matrice RBAC effective
| Outil | direction | manager | expert | cons_sr | cons_jr | alternant | stagiaire | support |
|---|---|---|---|---|---|---|---|---|
| **Intranet** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Gitea** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Code Server** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| **n8n** | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| **Portainer** | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| **Uptime Kuma (Status)** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| **Traefik Dashboard** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Voir aussi `matrices/rbac-matrix.md` pour la vue détaillée.
---
## 🔄 OAuth2-Proxy — Activer le scope des rôles
Modifier le `.env` de **chaque** OAuth2-Proxy pour demander le scope des rôles :
```env
OAUTH2_PROXY_SCOPE=openid email profile urn:zitadel:iam:org:project:roles
```
Puis restart :
```bash
cd ~/docker/oauth2-proxy-
docker compose down
docker compose up -d
```
---
## 🎬 Workflow complet : du recrutement au compte fonctionnel
```
1. Nouveau collaborateur arrive
│
▼
2. RH crée la fiche dans Furious Squad (job_title, manager, BU, etc.)
│
│ Le jour J ou J+1
▼
3. Sync Furious → Zitadel
- Soit manuel : python3 import-furious-to-zitadel.py
- Soit auto : workflow n8n (à mettre en place)
│
▼
4. Génération du mapping : python3 generate-roles-mapping.py
→ roles-mapping.json mis à jour
│
▼
5. Copie vers l'intranet : cp roles-mapping.json ~/docker/intranet/
→ nginx ne nécessite pas de restart (volume monté)
│
▼
6. Attribution du rôle : python3 assign-roles.py
→ Le user reçoit son rôle dans Zitadel
│
▼
7. Distribution du mdp temporaire via Teams
│
▼
8. User se logge → voit les bonnes cartes selon son rôle
```
---
## 🐛 Troubleshooting RBAC
### "Toutes les cartes sont visibles, le filtrage ne marche pas"
#### Vérification 1 : le sub_filter nginx fonctionne ?
```bash
# Depuis le serveur, vérifier que le HTML rendu contient le bon email
docker exec intranet sh -c "curl -s -H 'X-Forwarded-Email: test@seizeconsulting.com' http://localhost/ | grep 'USER_EMAIL'"
# Doit afficher : const USER_EMAIL = "test@seizeconsulting.com";
```
Si le HTML contient encore `__USER_EMAIL__` :
- Vérifier que `nginx-rbac.conf` est bien monté dans le conteneur
- Vérifier les logs nginx : `docker logs intranet`
#### Vérification 2 : roles-mapping.json est chargé ?
Ouvrir la console JS du browser (F12) :
```
[RBAC] User: xxx | Rôle: xxx
```
Si Rôle = `null` :
- Vérifier que l'email est bien dans roles-mapping.json
- Attention à la casse (le script fait `.toLowerCase()`)
#### Vérification 3 : la matrice JS est correcte ?
Dans la console :
```js
document.querySelectorAll('.service-card[data-app]').forEach(c => console.log(c.dataset.app, c.style.display));
```
Doit afficher chaque carte avec son `display: none` ou `display: ""`.
### "Le user voit __USER_EMAIL__ littéralement"
Cause : nginx ne fait pas le sub_filter.
Solutions :
1. Vérifier que `nginx-rbac.conf` est bien monté en RO sur `/etc/nginx/nginx.conf` (pas un autre chemin)
2. Vérifier que le header `X-Forwarded-Email` arrive bien (debug : tail logs nginx)
3. Restart : `docker compose down && docker compose up -d`
### "Le user voit ses cartes mais quand il clique sur une carte non-autorisée, il y accède quand même"
C'est **normal** et c'est la limite acceptée de l'Approche A.
Pour vrai RBAC, voir [DECISIONS.md D7](../DECISIONS.md).
### "Un user vient d'être ajouté dans Furious mais ne voit aucune carte"
Causes :
1. roles-mapping.json pas à jour → relancer `generate-roles-mapping.py` + copier
2. User pas encore dans Zitadel → relancer l'import
3. job_title pas dans le mapping → ajouter dans `JOB_TITLE_TO_ROLE` du script
---
## 🔄 Mise à jour de la matrice RBAC
### Cas 1 : Ajouter un nouvel outil
1. Ajouter la carte HTML dans `index.html` avec `data-app="newapp"`
2. Ajouter la ligne dans `ACCESS_MATRIX` :
```javascript
"newapp": ["direction", "manager"],
```
3. Restart : `cd ~/docker/intranet && docker compose restart`
### Cas 2 : Changer les autorisations d'un outil
1. Modifier la liste de rôles dans `ACCESS_MATRIX` du JS
2. Restart : `docker compose restart`
3. Tester avec différents profils
### Cas 3 : Ajouter un nouveau rôle
1. Créer le rôle dans Zitadel (Projects → Roles → New)
2. Mettre à jour le mapping dans `assign-roles.py` (variable `JOB_TITLE_TO_ROLE`)
3. Mettre à jour `ACCESS_MATRIX` dans le JS pour préciser ce que ce rôle voit
4. Lancer `generate-roles-mapping.py` + `assign-roles.py`
5. Copier `roles-mapping.json` vers l'intranet
6. Restart intranet
---
## 🎨 Personnalisation visuelle
Le CSS de l'intranet est dans `