docs(domaines): documentation par domaine fonctionnel (7 fiches)
All checks were successful
All checks were successful
docs/domaines/ : une fiche par domaine livre (perimetre / ce qui est livre / regles metier RG-T* / decisions -> ADR / tables), + index. auth, catalogue, stock-recettes, users, rbac, stats, borne. Commande = P4 (schema pret, non documentee ici). Troisieme et derniere PR du jeu de documentation socle.
This commit is contained in:
parent
33e6901e7c
commit
f7caf2d50c
8 changed files with 225 additions and 0 deletions
18
docs/domaines/README.md
Normal file
18
docs/domaines/README.md
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Documentation par domaine
|
||||||
|
|
||||||
|
Une fiche par domaine fonctionnel livre : **perimetre**, **ce qui est livre** (code +
|
||||||
|
routes), **regles metier** (RG-T* de `docs/merise/mlt.md`), **decisions** (renvoi
|
||||||
|
`docs/adr/`), **tables**. Vue d'ensemble : `docs/ARCHITECTURE.md`.
|
||||||
|
|
||||||
|
**Auteur : BYAN** (formalisation ; arbitrage et validation par l'auteur).
|
||||||
|
|
||||||
|
| Domaine | Fiche | Statut |
|
||||||
|
|---|---|---|
|
||||||
|
| Authentification & sessions | [auth.md](auth.md) | Livre (P2) |
|
||||||
|
| Catalogue (categories, produits, menus) | [catalogue.md](catalogue.md) | Livre (P3) |
|
||||||
|
| Stock & recettes (ingredients) | [stock-recettes.md](stock-recettes.md) | Livre (P3) |
|
||||||
|
| Comptes utilisateurs | [users.md](users.md) | Livre (P3) |
|
||||||
|
| RBAC (roles & permissions) | [rbac.md](rbac.md) | Livre (P3) |
|
||||||
|
| Statistiques | [stats.md](stats.md) | Livre (P3, KPIs vente differes P4) |
|
||||||
|
| Borne (kiosk) | [borne.md](borne.md) | Front P5 (API au swap P4) |
|
||||||
|
| Commande | — | P4 (schema pret, workflow a venir) |
|
||||||
29
docs/domaines/auth.md
Normal file
29
docs/domaines/auth.md
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Domaine — Authentification & sessions
|
||||||
|
|
||||||
|
## Perimetre
|
||||||
|
Connexion back-office, deconnexion, reinitialisation de mot de passe, garde de session,
|
||||||
|
PIN d'action sensible. Pas d'auth cote borne (front public).
|
||||||
|
|
||||||
|
## Ce qui est livre
|
||||||
|
- `App\Auth\AuthService` (login 12.1 / logout 12.2), `PasswordResetService` (12.3).
|
||||||
|
- `SessionManager` (seul a toucher `$_SESSION`/cookie, mode test memoire), `SessionGuard`
|
||||||
|
(RG-6/RG-T02 : idle 4h, absolu 10h, `is_active`), `Csrf` (jeton synchroniseur).
|
||||||
|
- `PasswordHasher` (argon2id + leurre de timing), `PinVerifier`, `PinThrottle`,
|
||||||
|
`ThrottlePolicy` (backoff degressif).
|
||||||
|
- Controleurs `AuthController`, `PasswordResetController`, `ProfileController` (set-PIN
|
||||||
|
self-service), `MeController` (`/api/me`).
|
||||||
|
|
||||||
|
## Regles metier
|
||||||
|
- RG-6 / RG-T02 : session valide (idle + absolu + compte actif) sinon 302 `/login`.
|
||||||
|
- RG-8 / RG-9 : throttle login par compte + par IP (`login_throttle`), backoff degressif.
|
||||||
|
- RG-T13 : PIN d'action sensible (voir [users](users.md), [rbac](rbac.md), stock).
|
||||||
|
- Anti-enumeration : reponses neutres (reset, login) ; leurre de timing argon2id.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
[ADR-0001](../adr/0001-php-from-scratch-sans-composer.md) (from scratch),
|
||||||
|
[ADR-0004](../adr/0004-pin-action-sensible-audit.md) (PIN),
|
||||||
|
[ADR-0005](../adr/0005-throttle-pin-separe-du-login.md) (throttle PIN).
|
||||||
|
|
||||||
|
## Tables
|
||||||
|
`user`, `login_throttle`, `pin_throttle`, `audit_log` (login + pin.failed). Detail :
|
||||||
|
`docs/merise/mlt.md` section 12 + 22.
|
||||||
31
docs/domaines/borne.md
Normal file
31
docs/domaines/borne.md
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Domaine — Borne (kiosk)
|
||||||
|
|
||||||
|
## Perimetre
|
||||||
|
Front client tactile (Bloc 1) : parcours welcome -> categories -> produit -> panier ->
|
||||||
|
confirmation. HTML/CSS/JS vanilla, servi en statique par Apache.
|
||||||
|
|
||||||
|
## Ce qui est livre
|
||||||
|
- Pages : `index`, `categories`, `products`, `product`, `cart`, `payment`,
|
||||||
|
`confirmation` (`src/public/borne/`).
|
||||||
|
- JS modules ES6 (`assets/js/`) : `data.js` (chargement, point de swap P4), `state.js`
|
||||||
|
(panier), `page-*.js`, `nav.js`, et `allergens.js` (modale generale 14 INCO sur carte
|
||||||
|
et fiche).
|
||||||
|
- Donnees : JSON statiques (`data/`) en P5 ; basculent sur `/api/*` DB-backed au swap P4.
|
||||||
|
|
||||||
|
## Regles metier / conventions
|
||||||
|
- Allergenes : info **generale** (les 14 INCO, reglement UE 1169/2011), pas un calcul
|
||||||
|
par produit (mapping `ingredient_allergen` differe).
|
||||||
|
- CSP-safe pour le code projet : pas de script inline ajoute (donnees via `data-*`,
|
||||||
|
`addEventListener`). Source allergenes = liste fixe `data/allergens.json`, se branchera
|
||||||
|
sur `/api/allergens` au swap P4.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
Harnais front `node:test` + jsdom (`tests/js/allergens.test.js`) : 14 INCO, bouton "i",
|
||||||
|
ouverture/fermeture (bouton/overlay/Echap), idempotence. Job CI `js-tests` (Node 20).
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
Swap point P5 -> API au P4 (cf. `data.js` + journaux). Modele = app self-hostable
|
||||||
|
([ADR-0009](../adr/0009-compose-standalone-et-prod-gitignore.md)).
|
||||||
|
|
||||||
|
## Tables (au swap P4)
|
||||||
|
`category`, `product`, `menu` + `allergen` (lecture). Aujourd'hui : JSON statiques.
|
||||||
29
docs/domaines/catalogue.md
Normal file
29
docs/domaines/catalogue.md
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Domaine — Catalogue (categories, produits, menus)
|
||||||
|
|
||||||
|
## Perimetre
|
||||||
|
CRUD des categories, produits et menus composes (borne de base + slots). Base du
|
||||||
|
catalogue consomme par la borne.
|
||||||
|
|
||||||
|
## Ce qui est livre
|
||||||
|
- Repositories : `CategoryRepository`, `ProductRepository`, `MenuRepository`.
|
||||||
|
- Controleurs : `CategoryController` (`category.manage`), `ProductController`
|
||||||
|
(`product.read/create/update/delete`), `MenuController` (`menu.read/create/update/delete`).
|
||||||
|
- Menus composes : burger de base + `menu_slot` / `menu_slot_option`, editeur slots en
|
||||||
|
JS vanilla CSP-safe (champ cache `slots_json`), reecriture delete-and-reinsert en tx.
|
||||||
|
|
||||||
|
## Regles metier
|
||||||
|
- RG-T16 (allowlist colonnes), RG-T18 (validation serveur bornee : prix > 0, TVA dans
|
||||||
|
{55,100}, etc.), RG-T15 (sorties echappees).
|
||||||
|
- Produit : PIN equipier + audit UNIQUEMENT si prix ou TVA change (mlt 8.2 RG-4) ;
|
||||||
|
suppression = PIN + audit (8.3). Menu : suppression = PIN + audit (8.6).
|
||||||
|
- Pas de suppression dure si reference (FK RESTRICT depuis order_item / menu / selection)
|
||||||
|
-> 409, alternative = desactivation (`is_available`).
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
[ADR-0002](../adr/0002-back-office-mvc-rendu-serveur.md) (MVC serveur),
|
||||||
|
[ADR-0006](../adr/0006-http-409-conflit-422-validation.md) (409/422),
|
||||||
|
[ADR-0004](../adr/0004-pin-action-sensible-audit.md) (PIN + audit).
|
||||||
|
|
||||||
|
## Tables
|
||||||
|
`category`, `product`, `menu`, `menu_slot`, `menu_slot_option`. Detail :
|
||||||
|
`docs/merise/mlt.md` section 8.
|
||||||
30
docs/domaines/rbac.md
Normal file
30
docs/domaines/rbac.md
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Domaine — RBAC (roles & permissions)
|
||||||
|
|
||||||
|
## Perimetre
|
||||||
|
Gestion des roles et de la matrice role/permission (mlt 10.4 MANAGE_RBAC), permission
|
||||||
|
`role.manage`. Catalogue de permissions fige au seed (lecture seule).
|
||||||
|
|
||||||
|
## Ce qui est livre
|
||||||
|
- `RoleRepository` (App\Auth) : roles (CRUD, code immuable), permissions (lecture),
|
||||||
|
matrice (`permissionIdsFor`/`permissionCodesFor`, `setPermissions` tx +
|
||||||
|
`replacePermissions` raw), `role_visible_source` (`setVisibleSources` / raw).
|
||||||
|
- `RoleController` (`role.manage`) : index, create/store (role custom RG-4), edit/update
|
||||||
|
(champs role + matrice + sources visibles en UNE transaction). Vues `admin/roles/{index,form}`.
|
||||||
|
- Matrice soumise en champs **scalaires** (`perm_<id>`, `source_<enum>`) : `Request::formBody`
|
||||||
|
ne garde que les scalaires (pas de `name[]`, pas de JS).
|
||||||
|
|
||||||
|
## Regles metier
|
||||||
|
- RG-6 (mlt 10.4) : PIN equipier + `audit_log` (`role.manage`) dans une transaction ;
|
||||||
|
`details` JSON = **diff** des codes de permission (ajoutes/retires), calcule avant la
|
||||||
|
reecriture delete-and-reinsert.
|
||||||
|
- `Authorizer::can` recharge les permissions a chaque verification (effet immediat).
|
||||||
|
- Garde-fous anti-lockout : le role `admin` conserve `role.manage` ET reste actif ;
|
||||||
|
`code` immuable apres creation ; `order_source` borne a l'ENUM ; code dupli -> 409.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
[ADR-0004](../adr/0004-pin-action-sensible-audit.md) (PIN + audit),
|
||||||
|
[ADR-0006](../adr/0006-http-409-conflit-422-validation.md) (409).
|
||||||
|
|
||||||
|
## Tables
|
||||||
|
`role`, `permission`, `role_permission`, `role_visible_source`, `audit_log`. Detail :
|
||||||
|
`docs/merise/mlt.md` section 10.4.
|
||||||
26
docs/domaines/stats.md
Normal file
26
docs/domaines/stats.md
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Domaine — Statistiques
|
||||||
|
|
||||||
|
## Perimetre
|
||||||
|
Tableau de bord de pilotage (mlt domaine 11), permission `stats.read`. Landing par
|
||||||
|
defaut du role manager.
|
||||||
|
|
||||||
|
## Ce qui est livre
|
||||||
|
- `StatsRepository` : `counts()` (compteurs catalogue : produits/menus/categories/
|
||||||
|
ingredients, total + actifs/disponibles), `stockHealth()` (repartition des ingredients
|
||||||
|
actifs par bande RG-T21 + liste d'alerte triee du plus critique).
|
||||||
|
- `StatsController` (`stats.read`) -> `/admin/stats` + vue `admin/stats/index` (cartes
|
||||||
|
KPI + table d'alerte stock) + lien nav "Pilotage".
|
||||||
|
|
||||||
|
## Regles metier / perimetre
|
||||||
|
- KPIs sur les **donnees disponibles** en P3 : sante catalogue + stock. **Ferme le 404**
|
||||||
|
du landing manager (`role.default_route = /admin/stats`).
|
||||||
|
- KPIs de **vente** (CA, volumes, `service_day`) = **P4** : ils dependent du domaine
|
||||||
|
commande (encore en schema seul).
|
||||||
|
- Sante stock = reutilise `IngredientRepository::stockBand` (source unique RG-T21).
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
[ADR-0003](../adr/0003-stock-pourcentage-dispo-calculee.md) (bandes RG-T21).
|
||||||
|
|
||||||
|
## Tables
|
||||||
|
Lecture seule : `product`, `menu`, `category`, `ingredient` (compteurs + bandes).
|
||||||
|
KPIs vente (P4) : `customer_order`, `order_item`. Detail : `docs/merise/mlt.md` section 11.
|
||||||
31
docs/domaines/stock-recettes.md
Normal file
31
docs/domaines/stock-recettes.md
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Domaine — Stock & recettes (ingredients)
|
||||||
|
|
||||||
|
## Perimetre
|
||||||
|
Gestion des ingredients, du stock (reappro + inventaire), des mouvements de stock, et de
|
||||||
|
la composition des produits (recettes). Sous-tend la disponibilite produit calculee.
|
||||||
|
|
||||||
|
## Ce qui est livre
|
||||||
|
- `IngredientRepository` : CRUD, stock %/bande calcules, `restock` (tx), `inventoryCount`
|
||||||
|
(tx, ecrit une ligne meme a delta=0, RG-3), `movements` (borne), `isReferenced`.
|
||||||
|
- `IngredientController` : CRUD (`ingredient.manage`, sans PIN), RESTOCK (`stock.manage`,
|
||||||
|
sans PIN), INVENTORY_COUNT (`stock.count` + PIN), mouvements (`stock.read`).
|
||||||
|
- `ProductRepository` : composition (`product_ingredient`), `setComposition`
|
||||||
|
(delete-and-reinsert tx), `isOrderable` (RG-T21), `autoUnavailableIds`.
|
||||||
|
- Editeur de recette (`ProductController::recipeForm/saveRecipe`, `ingredient.manage`).
|
||||||
|
|
||||||
|
## Regles metier
|
||||||
|
- RG-T13 : INVENTORY_COUNT seule action sensible du stock (PIN equipier) ; succes ->
|
||||||
|
`stock_movement.user_id`, **sans** `audit_log` (RG-T14 : le mouvement EST la trace).
|
||||||
|
RESTOCK et CRUD ingredient ne sont PAS sensibles.
|
||||||
|
- RG-T22 : echec PIN inventaire -> `pin.failed` + throttle dans une transaction.
|
||||||
|
- RG-T21 : disponibilite produit calculee (cf. [ADR-0003](../adr/0003-stock-pourcentage-dispo-calculee.md)).
|
||||||
|
- FK : `product_ingredient`/`stock_movement` RESTRICT sur l'ingredient (hard-delete -> 409) ;
|
||||||
|
`product_ingredient.product_id` CASCADE (trace du nombre de lignes a la suppression, dette #27).
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
[ADR-0003](../adr/0003-stock-pourcentage-dispo-calculee.md) (stock % + RG-T21),
|
||||||
|
[ADR-0004](../adr/0004-pin-action-sensible-audit.md) / RG-T14 (attribution sans double-journal).
|
||||||
|
|
||||||
|
## Tables
|
||||||
|
`ingredient`, `product_ingredient`, `stock_movement`, `allergen`, `ingredient_allergen`
|
||||||
|
(mapping differe). Detail : `docs/merise/mlt.md` sections 8.8 + 9.
|
||||||
31
docs/domaines/users.md
Normal file
31
docs/domaines/users.md
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Domaine — Comptes utilisateurs
|
||||||
|
|
||||||
|
## Perimetre
|
||||||
|
Gestion des comptes back-office (mlt domaine 10.1-10.3 + 10.5) : creation, edition,
|
||||||
|
desactivation, reinitialisation de PIN, effacement RGPD.
|
||||||
|
|
||||||
|
## Ce qui est livre
|
||||||
|
- `UserRepository` (App\Auth) : all (JOIN role) / find / emailExists / activeRoleExists /
|
||||||
|
create / update (allowlist) / setPasswordHash / clearPin / deactivate / anonymise /
|
||||||
|
activeAdminCount / isAdmin.
|
||||||
|
- `UserController` : index (`user.read`), create/store (`user.create`), edit/update
|
||||||
|
(`user.update`), deactivate (`user.deactivate`), reset-pin, erase-PII. Vues
|
||||||
|
`admin/users/{index,form,confirm}`.
|
||||||
|
|
||||||
|
## Regles metier
|
||||||
|
- RG-T13/14 : **toutes** les mutations sont sensibles -> PIN equipier + `audit_log`
|
||||||
|
(`user.create/update/deactivate/erase_pii`) dans la meme transaction ; `details` JSON =
|
||||||
|
noms de champs / role (pas de PII). Throttle RG-T22.
|
||||||
|
- RG-T16 : allowlist (email/prenom/nom/role_id/is_active) ; `is_active` pose serveur a
|
||||||
|
la creation. Unicite email -> 409.
|
||||||
|
- Self-protection : pas d'auto-desactivation (403 SELF_DEACTIVATION) ; on ne retire pas
|
||||||
|
le statut du **dernier admin actif** (update/deactivate/erase) ; effacement deja fait -> 409.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
[ADR-0004](../adr/0004-pin-action-sensible-audit.md) (PIN + audit),
|
||||||
|
[ADR-0007](../adr/0007-rgpd-anonymisation-tombstone.md) (anonymisation RGPD),
|
||||||
|
[ADR-0006](../adr/0006-http-409-conflit-422-validation.md) (409/422).
|
||||||
|
|
||||||
|
## Tables
|
||||||
|
`user` (+ `anonymized_at` pour RGPD), `audit_log`, `role` (FK). Detail :
|
||||||
|
`docs/merise/mlt.md` section 10.1-10.5.
|
||||||
Loading…
Add table
Reference in a new issue