La plupart des applications CRUD démarrent avec des « rôles » qui finissent écrits sur mesure à la main pour chaque endpoint. Un an plus tard, personne ne peut répondre à la question « qui peut approuver une note de retour ? » sans lire le code.
La descente vers le chaos des permissions suit un chemin prévisible. D'abord, un simple contrôle if user.is_staff sur les endpoints les plus sensibles. Puis quelques classes de permission personnalisées. Ensuite des overrides par tenant parce que « notre plus gros client a une structure d'équipe différente. » En un an, les permissions sont dispersées entre les vues, les sérialiseurs et les conditionnels du frontend, et la seule façon de savoir ce qu'un utilisateur donné peut faire est de se connecter à sa place et d'essayer.
Quatre groupes, une matrice Quotery fournit quatre groupes : admin, manager, commercial, warehouse. La matrice de permissions est documentée dans le CLAUDE.md — un tableau unique indiquant qui peut créer, lire, modifier ou supprimer quoi. L'ajout d'une nouvelle fonctionnalité commence toujours par « ajouter la ligne à la matrice, puis câbler le contrôle ».
La matrice est volontairement plate et volontairement réduite. Admin peut tout faire. Manager peut tout faire, sauf les changements de configuration au niveau du tenant. Commercial peut créer et gérer les devis, consulter ses propres clients, et consulter la disponibilité du stock (sans le modifier). Warehouse peut gérer le stock, enregistrer les livraisons, traiter les retours, et consulter les données liées à l'exécution. Quatre lignes, peut-être huit colonnes. Si une permission ne tient pas dans cette matrice, la conception de la fonctionnalité est probablement trop complexe.
Visibilité par ligne
Les utilisateurs commercial voient leurs propres devis ; admin et manager voient tout le tenant. La couche de service l'impose — la vue se contente de transmettre request.user.
C'est là que réside la subtilité. L'appartenance à un groupe contrôle l'accès grossier (cet utilisateur peut-il clôturer des devis ?). Le périmètre par ligne contrôle l'accès fin (quels devis cet utilisateur peut-il clôturer ?). Les utilisateurs commercial passent les deux contrôles : ils disposent de la permission « peut clôturer un devis », et leur requête est limitée aux devis qu'ils possèdent. Un utilisateur warehouse échoue au premier contrôle — il n'atteint jamais le second. Les deux mécanismes sont indépendants mais se composent proprement.
Pourquoi pas des ACL granulaires Nous avons choisi une approche par groupes parce que le coût des ACL granulaires se paie sur chaque requête, pour toujours. Une équipe de 20 n'a pas 20 rôles ; elle en a 4. La hiérarchie est plate par conception.
Les ACL granulaires (permissions au niveau de l'utilisateur sur des ressources individuelles) sont la bonne réponse pour certains domaines — les plateformes de partage de documents, les outils de gestion de projet, tout ce qui repose sur le partage ad hoc comme fonctionnalité centrale. Les opérations de distribution ne relèvent pas de ce domaine. Les processus sont structurés, les rôles sont stables, et les frontières de permissions s'alignent sur les frontières organisationnelles. Un modèle par groupes se transpose proprement au métier réel : les commerciaux font le travail commercial, les magasiniers le travail d'entrepôt, les managers supervisent les deux, et les admins configurent le système. Ajouter des ACL par utilisateur à ce modèle ajouterait de la complexité sans ajouter de capacité.
