feat: le responsable peut lire et annuler les commandes (remplace D5 sur ce point) #176

Merged
Corentin merged 1 commit from feat/manager-cancel into dev 2026-09-27 16:50:54 +02:00
Owner

Le role Responsable (manager) recoit order.read et order.cancel. Decision de l'auteur, fiche docs/adr/0020-responsable-annule-commande.md, qui remplace la decision D5 sur ce seul point.

Pourquoi

En restauration rapide, l'annulation d'une vente est l'acte reserve au responsable : c'est la parade classique contre la fraude de caisse la plus simple (encaisser, puis annuler). D5 faisait l'inverse : le comptoir et le drive pouvaient annuler, le responsable non, et il ne voyait meme pas la liste des commandes de son service.

Ce qui change

  • order.read + order.cancel pour le manager. Le comptoir et le drive gardent leur annulation. Le catalogue reste a 23 permissions.
  • Migration 0018 pour les bases installees, jeu de donnees 0001 pour les installations neuves : un test verifie que les deux aboutissent au meme ensemble de droits.
  • La description du role n'est mise a jour que si elle est encore le texte d'origine, compare octet par octet : la collation de la colonne ignore les accents, une egalite simple aurait ecrase une retouche faite a la main sur un seul accent. Test inverse d'abord, rouge, puis vert.
  • Aucun garde-fou affaibli : code personnel de l'equipier qui agit, audit dans la meme transaction, remise en stock si payee. Le manager voit tous les canaux.

Demonstration et documentation

  • Matrice RBAC : M2 devient une annulation reussie ; la separation des pouvoirs se montre par le refus de creer un compte (M5).
  • Comptes de demonstration, page de demonstration de l'API, collections Postman et Bruno regenerees depuis scripts/gen_postman.py.
  • Plan d'oral : le refus de 29:00 se joue desormais avec le compte cuisine, qui voit les commandes mais ne peut pas les annuler.
  • Index des fiches de decision complete avec 0018 et 0019, oubliees dans leurs propres PR.

Verifications

Controle Resultat
gitleaks, tout l'historique de la branche 315 commits, aucune fuite
PHPUnit (MariaDB reelle) 2352 tests, 7791 assertions, 0 echec
PHPStan niveau 6 0 erreur
Tests JavaScript 399, 0 echec
Navigateur reel, pile jetable le comptoir cree C1 ; le manager la voit, l'annule avec son code (« Commande annulée. », etat cancelled confirme par l'API) ; la cuisine voit la liste mais l'annulation lui est refusee en 403 (page et API)

Limite assumee

Le comptoir garde la possibilite d'annuler seul : la fraude « encaisser puis annuler » reste tracee mais pas empechee. La cible metier (l'equipier lance, le code d'un responsable autorise) est nommee dans l'ADR comme evolution : c'est un changement de conception, pas une permission de plus.

Le role **Responsable** (`manager`) recoit `order.read` et `order.cancel`. Decision de l'auteur, fiche `docs/adr/0020-responsable-annule-commande.md`, qui remplace la decision D5 sur ce seul point. ## Pourquoi En restauration rapide, l'annulation d'une vente est l'acte reserve au responsable : c'est la parade classique contre la fraude de caisse la plus simple (encaisser, puis annuler). D5 faisait l'inverse : le comptoir et le drive pouvaient annuler, le responsable non, et il ne voyait meme pas la liste des commandes de son service. ## Ce qui change - `order.read` + `order.cancel` pour le manager. Le comptoir et le drive **gardent** leur annulation. Le catalogue reste a 23 permissions. - Migration `0018` pour les bases installees, jeu de donnees `0001` pour les installations neuves : un test verifie que les deux aboutissent au meme ensemble de droits. - La description du role n'est mise a jour que si elle est encore le texte d'origine, **compare octet par octet** : la collation de la colonne ignore les accents, une egalite simple aurait ecrase une retouche faite a la main sur un seul accent. Test inverse d'abord, rouge, puis vert. - Aucun garde-fou affaibli : code personnel de l'equipier qui agit, audit dans la meme transaction, remise en stock si payee. Le manager voit tous les canaux. ## Demonstration et documentation - Matrice RBAC : M2 devient une annulation reussie ; la separation des pouvoirs se montre par le refus de creer un compte (M5). - Comptes de demonstration, page de demonstration de l'API, collections Postman et Bruno regenerees depuis `scripts/gen_postman.py`. - **Plan d'oral** : le refus de 29:00 se joue desormais avec le compte **cuisine**, qui voit les commandes mais ne peut pas les annuler. - Index des fiches de decision complete avec 0018 et 0019, oubliees dans leurs propres PR. ## Verifications | Controle | Resultat | |---|---| | gitleaks, tout l'historique de la branche | 315 commits, aucune fuite | | PHPUnit (MariaDB reelle) | 2352 tests, 7791 assertions, 0 echec | | PHPStan niveau 6 | 0 erreur | | Tests JavaScript | 399, 0 echec | | Navigateur reel, pile jetable | le comptoir cree C1 ; le manager la voit, l'annule avec son code (« Commande annulée. », etat `cancelled` confirme par l'API) ; la cuisine voit la liste mais l'annulation lui est refusee en 403 (page et API) | ## Limite assumee Le comptoir garde la possibilite d'annuler seul : la fraude « encaisser puis annuler » reste tracee mais pas empechee. La cible metier (l'equipier lance, le code d'un responsable autorise) est nommee dans l'ADR comme evolution : c'est un changement de conception, pas une permission de plus.
feat: the manager role can read and cancel orders (supersedes decision D5 on this point)
All checks were successful
CI / secret-scan (push) Successful in 21s
CI / php-lint (push) Successful in 25s
CI / static-tests (push) Successful in 2m37s
CI / js-tests (push) Successful in 43s
CI / shell-tests (push) Successful in 7s
CI / secret-scan (pull_request) Successful in 25s
CI / php-lint (pull_request) Successful in 26s
CI / static-tests (pull_request) Successful in 2m38s
CI / js-tests (pull_request) Successful in 38s
CI / shell-tests (pull_request) Successful in 7s
a8376b2c86
In fast food, voiding a sale is the act reserved to the shift manager: it is the
standard guard against the simplest till fraud (take the payment, then void it).
Decision D5 did the opposite: counter and drive could cancel, the manager could
not, and the manager could not even see the order list.

- manager gains order.read and order.cancel; counter and drive keep theirs; the
  permission catalogue stays at 23
- migration 0018 for installed databases, seed 0001 for fresh installs, tested to
  produce the same manager permission set; the role description is updated only if
  it is still the original text, compared byte for byte (the column collation is
  accent-insensitive, a plain equality would overwrite an accent-only manual edit)
- cancellation keeps every safeguard: acting user's PIN, audit line in the same
  transaction, restock when paid; the manager has no channel filter
- demo material updated: RBAC matrix (M2 becomes a successful cancel, M5 the
  separation-of-powers refusal on user.create), demo accounts, API demo page,
  Postman and Bruno collections regenerated from gen_postman.py
- oral rehearsal plan: the 29:00 refusal is now played with the kitchen account,
  which sees the orders but cannot cancel them
- ADR-0020; ADR index completed with 0018 and 0019, missing since their own PRs

PHPUnit 2352 green, PHPStan level 6 clean, 399 JS tests green.
Corentin scheduled this pull request to auto merge when all checks succeed 2026-09-27 16:42:40 +02:00
Sign in to join this conversation.
No reviewers
No labels
auto-merge
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
AcadeNice/corentin_wakdo!176
No description provided.