# 06-teams – Spécifications techniques

## 1. Modèle d’authz

- **Sujet** : `userId`.
- **Ressource** : `(boardId, scope)` où `scope` ∈ `{ board | subtree(containerId) | node(nodeId) }`.
- **Action primitive** (exemples) : `read`, `write-content`, `write-structure`, `set-state`, `set-progress`, `set-deadline`, `manage-relations`, `manage-actions`, `manage-logic`, `manage-teams`, `publish`, `manage-community`, `upload`.
- **Capability** : lot cohérent de primitives (ex. `content-editor`, `structure-editor`, `relations-manager`, `actions-runner`, `logic-admin`, `teams-admin`, `publisher`).
- **Rôle** : combinaison de capabilities (Owner, Maintainer, Contributor, Reader + customs).
- **Affectation** : tags `assigned/*` sont des signaux métier. Une règle builtin optionnelle : “peut modifier contenu + état des items où il est assigné”.

## 2. Héritage et résolution

- Un grant sur `board` s’applique à tout le board.
- Un grant sur `subtree(containerId)` s’applique au sous-arbre.
- Un grant sur `node(nodeId)` s’applique à ce node uniquement.
- **Deny** explicite sur un scope précis > grant plus large, sauf Owner (ignore les deny).
- Principe de moindre privilège : pas de droits implicites hors grants/rôles.
- Rôles customs = listes de capabilities ; modification d’un rôle répercute les capabilities associées immédiatement.

## 3. Vérification des droits

- **CommandBus** : chaque handler appelle une vérification `authorize(actorId, boardId, scope, primitive)` avant de produire le patch. Refus → `403 FORBIDDEN` (code symbolique).
- **Interactions/Logic** : l’acteur d’un run est l’utilisateur qui déclenche l’événement. Chaque effet issu d’un run vérifie les primitives requises pour chaque cible ; les cibles visibles mais non éditables peuvent être utilisées en lecture (conditions), jamais en écriture.
- **Sélection universelle** : filtrée par Teams → on ne peut pas sélectionner ce qu’on ne peut pas voir. Les cibles d’effets sont en plus filtrées par les droits d’édition.
- **Publish/Community** : `publish` ou `manage-community` requis en plus des droits de lecture sur les items publiés.
- **Owner** : bypass des deny, mais passe quand même par la vérification (utile pour le logging).

## 4. Structures de données (suggestion)

- Table/JSON `roles`: `{ id, label, capabilities[] }` (standard + customs).
- Table/JSON `memberships`: `{ userId, boardId, roleId, scopes[] }` où `scopes` liste de `board` ou `subtree(containerId)` ou `node(nodeId)`.
- Table/JSON `grants`: pour exceptions (deny/grant explicite sur scope).
- Flag board : `assignmentRuleEnabled` (active la règle builtin sur `assigned/*`).

## 5. Flux types

- **Vérification commande** : `MoveNode` → primitive `write-structure` sur parent source + parent cible ; refus si manque un des deux.
- **Run Interactions atomic** : chaque effet génère une commande ; avant envoi, vérifier que l’acteur possède les primitives associées (`create-item`, `set-state`, `manage-relations`, etc.) sur les cibles résolues.
- **Logique** : lors d’un veto ou d’une action générée, la vérification est identique (acteur = déclencheur de la règle). Aucune règle ne “se connecte” comme système pour bypasser.
- **Affectation** : si la règle builtin est active, un utilisateur est autorisé à `write-content` + `set-state` sur les items où `assigned/<user>` est présent (ou hérités d’un container assigné), sans conférer `write-structure` ni `manage-actions`.

## 6. Traçabilité et garde-fous

- Chaque commande logge : `actorId`, `boardId`, `nodeIds` touchés, `capability`/`primitive` consommée, `result`.
- Activity projette ces logs en respectant Teams (pas de fuite de nodes invisibles, détail masqué si nécessaire).
 - Safeguard “dernier owner” : toute opération qui retirerait ou rétrograderait le dernier Owner d’un board est refusée (`403`, code métier dédié, ex. `LAST_OWNER_PROTECTION`) et journalisée dans Activity.

## 7. Questions / risques

- Performance : cache des résolutions de scope pour gros boards (arbre + ACL).
- UX : rendre visible “d’où vient le droit” (rôle, scope, exception, affectation) ; outil de diagnostic.
- Conflits de rôles/customs : clarifier que deny scoped prime sur grant (sauf Owner).
