La Cafête implémente un système RBAC (Role-Based Access Control) avec des permissions granulaires suivant un motif CRUD en dot notation, et un rôle .manage qui agit comme super-permission pour chaque domaine.
Principe du wildcard .manage
Chaque domaine expose un permission .manage qui englobe toutes les permissions de ce domaine. Par exemple, card.manage donne accès à toutes les opérations sur les cartes (card.read, card.create, card.update, card.delete, etc.).
Les helpers du middleware (require_card_read, require_product_sell, etc.) vérifient soit la permission spécifique, soit la permission .manage correspondante.
Catalogue des permissions
Cartes
Code Description card.manageToutes les opérations sur les cartes (super-permission) card.readConsulter les cartes, soldes, QR, historique card.balance.readConsulter le solde (rôle porteur) card.history.readConsulter l'historique (rôle porteur) card.createCréer de nouvelles cartes card.updateModifier les infos carte, assigner/réassigner/révoquer/désactiver card.deleteSupprimer des cartes card.voidAnnuler des transactions card.manual_accessAccès manuel aux cartes (recherche admin) card.assign_newAttribuer une carte card.deactivateDésactiver une carte card.debit.lost_cardDébiter le solde d'une carte perdue card.recharge.cashRechargement en espèces card.recharge.mobile_moneyRechargement mobile money card.correctionCorrection de solde card.balance.manual_adjustPasser un solde en négatif (maternelle seulement) card.holder.createCréer des porteurs de carte card.holder.updateModifier des porteurs de carte card.holder.deleteSupprimer des porteurs de carte card.link.readVoir les liens parent-enfant card.link.createCréer des liens parent-enfant card.link.deleteSupprimer des liens parent-enfant
Enfant (fonctionnalités parent)
Code Description child.balance.readVoir le solde d'un enfant child.rechargeRecharger la carte d'un enfant child.history.readVoir l'historique des transactions d'un enfant
Produits
Code Description product.manageToutes les opérations sur les produits product.readVoir les produits product.createCréer des produits product.updateModifier des produits product.deleteSupprimer des produits product.sellVendre des produits (achat)
Catégories
Code Description category.createCréer des catégories category.updateModifier des catégories category.deleteSupprimer des catégories category.readVoir les catégories (souvent implicite via product.read)
Stock
Code Description stock.readVoir les mouvements de stock stock.adjustAjuster le stock manuellement stock.purchaseEnregistrer un achat de stock stock.produceEnregistrer une production de stock stock.transferEnregistrer un transfert de stock
Code Description menu.readVoir les menus menu.createCréer des menus menu.updateModifier des menus menu.deleteSupprimer des menus
Sites
Code Description site.manageToutes les opérations sur les sites site.readVoir les sites site.createCréer des sites site.updateModifier des sites site.deleteSupprimer des sites
Points de vente (POS)
Code Description pos.readVoir les points de vente pos.createCréer des points de vente pos.updateModifier des points de vente pos.deleteSupprimer des points de vente
Caisses (Registers)
Code Description register.readVoir les caisses register.openOuvrir une caisse register.closeFermer une caisse
Réservations
Code Description reservation.manageToutes les opérations sur les réservations reservation.readVoir les réservations reservation.createCréer des réservations reservation.updateModifier le statut des réservations reservation.validateValider une réservation (ready/collected) reservation.cancelAnnuler une réservation (déclenche le remboursement) reservation.refundRembourser des réservations reservation.exportExporter les réservations
Transactions
Code Description transaction.readVoir l'historique des transactions
Tickets support
Code Description ticket.readVoir les tickets support ticket.createCréer des tickets ticket.updateModifier des tickets
Notifications
Code Description notification.manageToutes les opérations sur les notifications notification.readVoir les templates et notifications planifiées notification.createCréer des templates et notifications planifiées notification.updateModifier des templates et notifications planifiées notification.deleteSupprimer des templates et notifications planifiées
Paramètres
Code Description settings.readVoir les paramètres de l'organisation settings.updateModifier les paramètres de l'organisation
Utilisateurs
Code Description user.manageToutes les opérations sur les utilisateurs user.readVoir les utilisateurs user.createCréer des utilisateurs user.updateModifier des utilisateurs user.deleteSupprimer des utilisateurs
Rôles
Code Description role.readVoir les rôles role.createCréer des rôles role.updateModifier des rôles role.deleteSupprimer des rôles role.permission.assignAssigner/retirer des permissions sur les rôles
Statistiques et Analytics
Code Description stats.exhaustive.readStatistiques cross-organisations stats.partial.readStatistiques d'organisation (héritage) analytics.readAnalytics de l'organisation log.readConsulter les logs log.manageGérer les logs (super-permission) anomaly.manageGérer les anomalies anomaly.threshold.configureConfigurer les seuils d'anomalie
Exports et imports
Code Description export.manageGérer/effectuer tous les exports import.manageGérer/effectuer tous les imports card.export / card.importExporter / importer des cartes cardholder.export / cardholder.importExporter / importer des porteurs product.export / product.importExporter / importer des produits transaction.exportExporter les transactions stock.exportExporter les mouvements de stock role.exportExporter les rôles log.exportExporter les logs anomaly.exportExporter les anomalies reservation.exportExporter les réservations
Super-permissions .manage complémentaires
Code Description cardholder.manageToutes les opérations sur les porteurs menu.manageToutes les opérations sur les menus stock.manageToutes les opérations de stock transaction.manageToutes les opérations sur les transactions user.manageToutes les opérations sur les utilisateurs role.manageToutes les opérations sur les rôles
Code Description platform.user.manageGérer les utilisateurs plateforme organization.manageGérer les organisations (niveau système)
Rôles système par défaut
Les rôles ci-dessous sont créés par la migration 0014 avec is_system_role = true.
Rôle (code) Ancien nom Description administrateursuper_adminAccès complet à toutes les fonctionnalités observateurorg_viewerLecture seule supportsupport_agentSupport technique limité gestionnaireadmin_n1Gestion complète de l'organisation superviseursupervisorSupervision et gestion caissiercashierOpérations de caisse et encaissement vendeursellerVentes uniquement porteurcard_holderSelf-service mobile
Détail des permissions par rôle
Les permissions ci-dessous correspondent au seed par défaut (seed_tenant_roles) et aux migrations. La matrice complète est disponible dans Matrice des rôles .
administrateur (super_admin)
Toutes les permissions système et tenant.
observateur (org_viewer)
Lecture seule : organization.manage, stats.exhaustive.read, stats.partial.read, plus les .read de chaque domaine (product, category, stock, card, site, pos, register, user, role, ticket, notification, settings, menu) et user.manage (héritage).
support (support_agent)
Support technique : organization.manage, user.manage, stats.partial.read et les .read de chaque domaine.
gestionnaire (admin_n1)
Toutes les permissions tenant (gestion complète de l'organisation).
superviseur (supervisor)
card.read, card.balance.read, card.history.read, card.manual_access, card.recharge.cash, card.recharge.mobile_money, card.correction, card.debit.lost_card, product.read, category.read, stock.read, menu.read, site.read, pos.read, register.read, reservation.read, reservation.create, reservation.update, reservation.refund, ticket.read, ticket.update, settings.read, user.read, role.read, notification.read, transaction.read, stats.partial.read, analytics.read, log.read, anomaly.manage.
caissier (cashier)
card.read, card.balance.read, card.history.read, card.recharge.cash, card.assign_new, card.manual_access, menu.read, stock.read, reservation.read, reservation.create, reservation.update, transaction.read, register.read, register.open, register.close.
vendeur (seller)
product.sell, product.read, category.read, stock.read, card.read, card.balance.read, menu.read, reservation.read, reservation.update, transaction.read.
porteur (card_holder)
card.balance.read, card.history.read, card.recharge.mobile_money.
Rôle
porteur réservé au mobile
Le rôle porteur est destiné aux utilisateurs de l'application mobile (porteurs de carte). Il ne doit pas être attribué au personnel, qui doit être vendeur, caissier, superviseur ou gestionnaire.
Hiérarchie des rôles
Plateforme (N2) ────────────────────────────────────────────────── │ ├── administrateur ────► toutes permissions ├── observateur ───────► lecture seule └── support ───────────► tickets + lecture Organisation (N1) ──────────────────────────────────────────────── │ ├── gestionnaire ─────► toutes permissions tenant ├── superviseur ──────► supervision (lecture + gestion courante) ├── caissier ─────────► opérations de caisse ├── vendeur ──────────► vente uniquement └── porteur ──────────► self-service mobile
Création de rôles custom
Les organisations peuvent créer des rôles supplémentaires (non-système) :
POST /api/v1/admin/org/roles Authorization: Bearer ... X-Tenant-Id: ... { "name": "gestionnaire_cuisine", "description": "Responsable de cuisine" }
Les rôles custom sont créés avec is_system_role = false et peuvent être supprimés. Les rôles système (administrateur, gestionnaire, etc.) ont is_system_role = true et sont protégés.
Assignation de permissions à un rôle
POST /api/v1/admin/org/roles/{id}/permissions Authorization: Bearer ... { "permission_id": "uuid-permission" }
Le catalogue des permissions est exposé par GET /api/v1/admin/org/permissions. Chaque permission s'assigne individuellement (une requête par permission).
Résolution des permissions au login
Les permissions sont résolues au login et embarquées dans le JWT pour éviter un lookup DB à chaque requête.
Login → Rôles → role_permissions → Permission codes → JWT claims
Le JWT contient un tableau plat de codes de permission.
Impact sur les modifications de rôles
Si un admin modifie les permissions d'un rôle après que des utilisateurs sont connectés :
Les tokens existants restent valides jusqu'à expiration (15 min)
Au prochain login ou refresh, les nouvelles permissions sont résolues
Le refresh token re-résout les permissions depuis la DB, donc un refresh suffit pour obtenir les permissions à jour sans re-login.
Vérification des permissions
Dans le code (middleware)
Le middleware vérifie les permissions sur chaque route. Par exemple, require_card_read accepte card.read ou card.manage :
Router :: new ( ) . route ( "/cards" , get ( list_cards ) ) . layer ( PermissionGuard :: new ( "card.read" ) )
Helper methods sur JwtClaims
claims . has_permission ( "card.read" ) claims . has_all_permissions ( & [ "card.read" , "card.recharge.cash" ] ) claims . has_any_permission ( & [ "card.read" , "card.manage" ] )
Principe de vérification
Les fonctions require_* du module authz utilisent un pattern systématique :
pub fn require_card_read ( claims : & JwtClaims ) -> bool { claims . has_any_permission ( & [ "card.read" , "card.manage" ] ) } pub fn require_product_sell ( claims : & JwtClaims ) -> bool { claims . has_any_permission ( & [ "product.sell" , "product.manage" ] ) }
Ainsi, {domaine}.manage donne automatiquement accès à toutes les permissions spécifiques de ce domaine.
Wildcard parent des permissions
Toutes les permissions d'un même domaine ne sont pas regroupées sous un seul .manage :
Domaine Wildcard parent card.*card.manageproduct.*product.managestock.*product.managecategory.*product.managemenu.*Aucun (permissions individuelles seulement) site.*site.managepos.*site.manageregister.*site.managereservation.*reservation.manageticket.*reservation.managenotification.*notification.manageuser.*user.manage (ou organization.manage)role.*organization.managesettings.*organization.managelog.readorganization.manageanalytics.*organization.manageanomaly.*organization.manage
Les fonctions require_* du middleware utilisent has_any_permission pour accepter soit la permission spécifique, soit le wildcard parent.
Permissions par endpoint
Tous les endpoints listés ci-dessous sont sous le préfixe /api/v1.
Cartes (endpoints publics / cardholder)
Endpoint Permission requise POST /cards/resolve-qrcard.readGET /cards/{id}/balancecard.readGET /cards/{id}/historycard.readGET /cards/public/{code}Aucune (public)
Cartes (administration)
Endpoint Permission requise GET /admin/org/cardscard.readPOST /admin/org/cardscard.createGET /admin/org/cards/{id}card.readPUT /admin/org/cards/{id}card.updateDELETE /admin/org/cards/{id}card.deletePOST /admin/org/cards/importcard.createPOST /admin/org/cards/{id}/assigncard.updatePOST /admin/org/cards/{id}/reassigncard.updatePOST /admin/org/cards/{id}/revokecard.updatePOST /admin/org/cards/{id}/deactivatecard.updatePOST /admin/org/cards/{id}/activatecard.updatePOST /admin/org/cards/{id}/lostcard.update
Porteurs
Endpoint Permission requise GET /admin/org/cards/holderscard.readPOST /admin/org/cards/holderscard.holder.createPUT /admin/org/cards/holders/{id}card.holder.updateDELETE /admin/org/cards/holders/{id}card.holder.deleteGET /admin/org/cards/holders/{id}/cardscard.readGET /admin/org/cards/holders/{id}/reservationscard.read
Liens parent-enfant
Endpoint Permission requise GET /admin/org/card-holder-linkscard.link.readPOST /admin/org/card-holders/{parent_id}/childrencard.link.createGET /admin/org/card-holders/{parent_id}/childrencard.link.readDELETE /admin/org/card-holders/{parent_id}/children/{child_id}card.link.delete
Transactions
Endpoint Permission requise GET /transactionstransaction.readPOST /transactions/rechargecard.recharge.cash ou card.recharge.mobile_moneyPOST /transactions/purchaseproduct.sellPOST /transactions/correctioncard.correctionPOST /transactions/refundreservation.refund (ou reservation.manage / card.correction / card.manage)POST /transactions/{id}/voidcard.void (ou card.correction)
Produits
Endpoint Permission requise GET /productsproduct.readPOST /productsproduct.createPUT /products/{id}product.updateDELETE /products/{id}product.delete
Stock (rattaché aux produits)
Endpoint Permission requise POST /admin/org/products/{id}/adjust-stockstock.adjustPOST /admin/org/products/{id}/purchasestock.purchasePOST /admin/org/products/{id}/productionstock.producePOST /admin/org/products/{id}/transferstock.transfer
Le wildcard pour les permissions stock est product.manage, non stock.manage.
Catégories
Endpoint Permission requise GET /admin/org/product-categoriesproduct.readPOST /admin/org/product-categoriescategory.createPUT /admin/org/product-categories/{id}category.updateDELETE /admin/org/product-categories/{id}category.delete
Le wildcard pour les permissions catégorie est product.manage.
Endpoint Permission requise GET /menusmenu.readPOST /menusmenu.createPUT /menus/{id}menu.updateDELETE /menus/{id}menu.delete
Sites
Endpoint Permission requise GET /admin/org/sitessite.readPOST /admin/org/sitessite.createGET /admin/org/sites/{id}site.readPUT /admin/org/sites/{id}site.updateDELETE /admin/org/sites/{id}site.delete
Points de vente
Endpoint Permission requise GET /admin/org/points-of-salepos.readPOST /admin/org/points-of-salepos.createPUT /admin/org/points-of-sale/{id}pos.updateDELETE /admin/org/points-of-sale/{id}pos.deletePOST /admin/org/points-of-sale/{id}/toggle-openpos.read
Le wildcard pour les permissions POS est site.manage.
Caisses
Endpoint Permission requise GET /admin/org/points-of-sale/{pos_id}/registersregister.readGET /admin/org/registers/{id}register.readPOST /admin/org/points-of-sale/{pos_id}/registers/openregister.openPOST /admin/org/registers/{id}/closeregister.close
Le wildcard pour les permissions registre est site.manage.
Réservations
Endpoint Permission requise GET /reservationsreservation.readPOST /reservationsreservation.createGET /reservations/{id}reservation.readPATCH /reservations/{id}/statusreservation.update
Tickets support
Endpoint Permission requise GET /admin/org/ticketsticket.readGET /admin/org/tickets/{id}ticket.readPOST /admin/org/ticketsticket.createPUT /admin/org/tickets/{id}ticket.updatePUT /admin/org/tickets/{id}/statusticket.updatePOST /admin/org/tickets/{id}/messagesticket.create
Le wildcard pour les permissions ticket est reservation.manage.
Notifications
Endpoint Permission requise GET /admin/org/notification-templatesnotification.readPOST /admin/org/notification-templatesnotification.createPUT /admin/org/notification-templates/{id}notification.updateDELETE /admin/org/notification-templates/{id}notification.deleteGET /admin/org/scheduled-notificationsnotification.readPOST /admin/org/scheduled-notificationsnotification.createPUT /admin/org/scheduled-notifications/{id}notification.updateDELETE /admin/org/scheduled-notifications/{id}notification.delete
Administration (organisation)
Endpoint Permission requise GET /admin/org/usersuser.readPOST /admin/org/usersuser.createPUT /admin/org/users/{id}user.updateDELETE /admin/org/users/{id}user.deleteGET /admin/org/rolesrole.readPOST /admin/org/rolesrole.createPUT /admin/org/roles/{id}role.updateDELETE /admin/org/roles/{id}role.deletePOST /admin/org/roles/{id}/permissionsrole.permission.assignGET /admin/org/settingssettings.readPUT /admin/org/settingssettings.updateGET /admin/org/logslog.readGET /admin/org/audit-loglog.readGET /admin/org/anomaliesanomaly.managePOST /admin/org/anomalies/{id}/acknowledgeanomaly.managePOST /admin/org/anomalies/{id}/resolveanomaly.manage
Le wildcard pour les permissions admin (user, role, settings, log, anomaly) est organization.manage.
Stats et analytics (organisation)
Endpoint Permission requise GET /admin/org/stats/dashboardanalytics.readGET /admin/org/stats/revenue-by-typeanalytics.readGET /admin/org/stats/top-productsanalytics.readGET /admin/org/stats/sites-revenueanalytics.readGET /admin/org/stats/hourlyanalytics.readGET /admin/org/stats/holdersanalytics.readGET /admin/org/stats/rechargesanalytics.readGET /admin/org/stats/salesanalytics.readGET /admin/org/stats/balancesanalytics.readGET /admin/org/stats/reservationsanalytics.readGET /admin/org/stats/stockstock.readGET /admin/org/analytics/*analytics.read
Endpoint Permission requise GET/POST /admin/system/usersplatform.user.manageGET/PUT/DELETE /admin/system/users/{id}platform.user.manageGET/POST/DELETE /admin/system/users/{id}/rolesplatform.user.manageGET/POST /admin/system/rolesorganization.manageGET/PUT/DELETE /admin/system/roles/{id}organization.managePOST/DELETE /admin/system/roles/{id}/permissionsorganization.manageGET /admin/system/permissionsorganization.manageGET/POST /admin/system/organizationsorganization.manageGET/PUT /admin/system/organizations/{id}organization.managePOST /admin/system/organizations/{id}/suspendorganization.managePOST /admin/system/organizations/{id}/activateorganization.manageGET /admin/system/audit-logstats.exhaustive.readGET /admin/system/anomaliesstats.exhaustive.readGET /admin/system/logslog.readGET /admin/system/stats/*stats.exhaustive.readGET /admin/system/analytics/*stats.exhaustive.read