docs: socle de documentation (ARCHITECTURE + guide developpeur)
All checks were successful
All checks were successful
Point d'entree technique pour le jury et les contributeurs. - docs/ARCHITECTURE.md : vue d'ensemble, stack, topologie de deploiement (5 services, standalone vs prod gitignore), demarrage une commande (wakdo-migrate), structure du code, flux d'une requete, securite (security-by-design : auth/RBAC/PIN+audit/throttle/ validation/RGPD), modele de donnees (22 tables + derivations calculees), tests & CI, methodologie. Renvoie vers PROJECT_CONTEXT / merise / adr (pas de duplication). - docs/DEVELOPER.md : lancer en local (docker compose up), migrations & seed, tests (PHPUnit .phar unit+integration, jsdom, PHPStan L6), conventions de code, git & CI. Premiere PR du jeu de documentation (socle). Suivront : docs/adr/ (registre de decisions) puis la doc par domaine.
This commit is contained in:
parent
9d75fabdca
commit
13d5cbab9d
2 changed files with 413 additions and 0 deletions
269
docs/ARCHITECTURE.md
Normal file
269
docs/ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,269 @@
|
||||||
|
# Architecture — Wakdo
|
||||||
|
|
||||||
|
Vue d'ensemble technique du projet (borne de commande fast-food, certification RNCP 37805).
|
||||||
|
Point d'entree pour comprendre la stack, le decoupage et les choix de conception.
|
||||||
|
|
||||||
|
- Scope metier, planning, mapping RNCP : `docs/PROJECT_CONTEXT.md`.
|
||||||
|
- Modelisation detaillee (entites, operations, regles) : `docs/merise/` (dictionary, mcd, mct, mlt).
|
||||||
|
- Decisions tracees : `docs/adr/` et `docs/journal/`.
|
||||||
|
|
||||||
|
**Auteur : BYAN** (formalisation ; arbitrage et validation par l'auteur du projet).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Vue d'ensemble
|
||||||
|
|
||||||
|
Wakdo simule une borne de commande tactile de restauration rapide, avec back-office
|
||||||
|
d'administration, workflow cuisine et API REST interne. Deux surfaces applicatives :
|
||||||
|
|
||||||
|
- **Borne (kiosk)** — front statique (HTML/CSS/JS vanilla ES6) servi par Apache,
|
||||||
|
consommant des donnees (JSON statique en P5, API DB-backed au swap P4).
|
||||||
|
- **Back-office + API** — application PHP rendue serveur (MVC maison) + endpoints
|
||||||
|
`/api/*`, derriere authentification et RBAC.
|
||||||
|
|
||||||
|
Trois canaux de commande (`source`) : `kiosk`, `counter`, `drive`. Le cycle de vie
|
||||||
|
d'une commande et la machine a etats sont decrits dans `docs/merise/` (domaine
|
||||||
|
commande = phase **P4**, schema en base mais workflow applicatif a venir).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Stack technique
|
||||||
|
|
||||||
|
| Couche | Techno | Note |
|
||||||
|
|---|---|---|
|
||||||
|
| Langage back | PHP 8.3 | from scratch, sans framework |
|
||||||
|
| Autoloader | PSR-4 manuel (`spl_autoload_register`) | namespace `App\` -> `src/app/` |
|
||||||
|
| Base de donnees | MariaDB 11.4 | PDO, requetes preparees uniquement |
|
||||||
|
| Serveur web | Apache httpd 2.4 (Alpine) | reverse FastCGI -> PHP-FPM |
|
||||||
|
| Serveur app | PHP-FPM 8.3 (Alpine) | execute le code back-office + API |
|
||||||
|
| Front borne | HTML5 + CSS3 + JS ES6 (modules) | vanilla, sans build |
|
||||||
|
| Conteneurisation | Docker + docker compose v2 | `docker compose up` = stack complete |
|
||||||
|
| Tests PHP | PHPUnit 11 (`.phar`, sans Composer) | unit + integration DB |
|
||||||
|
| Tests front | node:test + jsdom | harnais kiosk (`tests/js/`) |
|
||||||
|
| Analyse statique | PHPStan niveau 6 (`.phar`) | |
|
||||||
|
| CI/CD | Forgejo Actions | secret-scan, lint, tests, auto-merge |
|
||||||
|
| Versioning | Git + Forgejo (`git.acadenice.com`, miroir GitHub) | Conventional Commits |
|
||||||
|
|
||||||
|
Justifications (composer-less, from-scratch, etc.) : `docs/PROJECT_CONTEXT.md` section 6.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Topologie de deploiement
|
||||||
|
|
||||||
|
Cinq services Docker. Deux modes, par fichier compose :
|
||||||
|
|
||||||
|
- **`docker-compose.yml`** (versionne) — standalone : tourne en local sans configuration.
|
||||||
|
`wakdo-web` publie un port hote (`${HTTP_PORT:-8080}`), reseau interne seul.
|
||||||
|
- **`docker-compose.prod.yml`** (gitignore, propre a chaque hote) — meme stack exposee
|
||||||
|
via un reverse proxy Traefik (reseau externe + labels TLS), sans port hote.
|
||||||
|
|
||||||
|
```
|
||||||
|
[ docker compose up -d ]
|
||||||
|
|
|
||||||
|
wakdo-db (MariaDB 11.4, healthcheck)
|
||||||
|
| service_healthy
|
||||||
|
v
|
||||||
|
wakdo-migrate (one-shot : migrations + seed idempotents, puis sort)
|
||||||
|
| service_completed_successfully
|
||||||
|
+---------------+----------------+
|
||||||
|
v v
|
||||||
|
wakdo-app (PHP-FPM 8.3) wakdo-web (Apache)
|
||||||
|
^ FastCGI :9000 <-----------/ publie ${HTTP_PORT}:80 (mode local)
|
||||||
|
| ou labels Traefik (mode prod)
|
||||||
|
|
|
||||||
|
wakdo-db <-- PDO
|
||||||
|
|
||||||
|
wakdo-cron (dcron) : backup BDD + purges retention (RGPD)
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Reseau** : `wakdo_internal` (bridge) isole les services ; aucun port hote en mode
|
||||||
|
prod (acces par le proxy). En mode local, seul `wakdo-web` publie un port.
|
||||||
|
- **Volumes** : `wakdo_db_data` (persistance MariaDB), `wakdo_uploads` (images produits) ;
|
||||||
|
bind-mount `./var/backups` pour les dumps.
|
||||||
|
- **`wakdo-cron`** utilise `init: true` (tini comme PID 1 : dcron a besoin d'un init
|
||||||
|
parent pour `setpgid` sur ses jobs).
|
||||||
|
- Choix d'un **subnet RFC 1918 explicite** sur `wakdo_internal` cote prod : l'hote
|
||||||
|
mutualise a un allocateur Docker sature ; le subnet evite l'echec d'allocation auto.
|
||||||
|
|
||||||
|
Detail reseaux/volumes : `docs/PROJECT_CONTEXT.md` section 5.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Demarrage : une commande (Cr 7.c.4)
|
||||||
|
|
||||||
|
`docker compose up -d` amene une stack complete et utilisable :
|
||||||
|
|
||||||
|
1. `wakdo-db` demarre, devient *healthy* (script `healthcheck.sh` de l'image).
|
||||||
|
2. `wakdo-migrate` (service one-shot) applique, par le reseau et de maniere
|
||||||
|
**idempotente** :
|
||||||
|
- `db/migrations/*.sql` — suivi dans la table `schema_migrations` ;
|
||||||
|
- `db/seeds/*.sql` — suivi dans la table `seeds_applied`.
|
||||||
|
Relancer ne rejoue que les fichiers en attente. Le runner : `db/migrate-container.sh`.
|
||||||
|
3. `wakdo-app` et `wakdo-web` attendent la **completion** de `wakdo-migrate`
|
||||||
|
(`depends_on: service_completed_successfully`) avant de servir.
|
||||||
|
|
||||||
|
Le schema (DDL) et les donnees de reference (roles, permissions, catalogue, admin
|
||||||
|
bootstrap) sont donc en place sans etape manuelle. `db/migrate.sh` (hote, via
|
||||||
|
`docker exec`) reste disponible pour l'usage manuel / `--status`.
|
||||||
|
|
||||||
|
> Migration de mecanisme : sur une base **deja seedee** avant l'introduction du suivi
|
||||||
|
> (`seeds_applied` absente), back-filler la table avant le premier `up` (sinon re-seed
|
||||||
|
> -> conflits d'unicite). Volume vierge : aucun souci. Cf.
|
||||||
|
> `docs/journal/2026-06-17--makefile-to-compose-migrate.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Structure du code
|
||||||
|
|
||||||
|
Namespace `App\` -> `src/app/` (PSR-4 manuel). Front controller du vhost admin :
|
||||||
|
`src/public/admin/index.php` (Apache reecrit tout vers ce fichier ; le routeur voit
|
||||||
|
le `REQUEST_URI` intact).
|
||||||
|
|
||||||
|
```
|
||||||
|
src/app/
|
||||||
|
Core/ Autoloader, Config, Database (PDO), Request, Response, Router
|
||||||
|
Auth/ AuthService, SessionManager, SessionGuard, Authorizer, PinVerifier,
|
||||||
|
PinThrottle, ThrottlePolicy, PasswordHasher, Csrf, PasswordResetService,
|
||||||
|
UserRepository, RoleRepository, UserDirectory, Mailer/LogMailer
|
||||||
|
Catalogue/ Category / Product / Menu / Ingredient / Stats Repository
|
||||||
|
Controllers/ Admin (base), Authenticated (base), Auth, PasswordReset, Profile, Me,
|
||||||
|
Dashboard, Stats, Category, Product, Menu, Ingredient, User, Role,
|
||||||
|
Health, Home
|
||||||
|
Views/ admin/* (pages back-office rendues serveur), auth/* (login/reset)
|
||||||
|
src/public/
|
||||||
|
admin/ front controller + assets (CSS/JS) du back-office
|
||||||
|
borne/ front kiosk statique (index, categories, products, product, cart,
|
||||||
|
payment, confirmation) + assets JS modules + data JSON
|
||||||
|
```
|
||||||
|
|
||||||
|
Conventions transverses : controleurs non-`final` (seam de test : sous-classe injectant
|
||||||
|
des doubles via `db()` / `sessionManager()`) ; repository sur `DatabaseInterface` ;
|
||||||
|
chaque mutation passe par CSRF + validation serveur + allowlist (voir section 7).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Flux d'une requete back-office
|
||||||
|
|
||||||
|
```
|
||||||
|
Navigateur --(HTTPS via Traefik | HTTP local)--> wakdo-web (Apache)
|
||||||
|
| vhost par ServerName (APP_HOST_KIOSK -> public/borne, APP_HOST_ADMIN -> public/admin)
|
||||||
|
| PHP -> FastCGI :9000
|
||||||
|
v
|
||||||
|
wakdo-app (PHP-FPM) : src/public/admin/index.php
|
||||||
|
| Router (methode + chemin) -> [Controller, action]
|
||||||
|
v
|
||||||
|
Controller (extends AdminController)
|
||||||
|
| guard(permission) -> SessionGuard (RG-6/RG-T02 : session valide ?)
|
||||||
|
| + Authorizer::can(role, permission) (RG-T03, recharge DB)
|
||||||
|
| (mutation) Csrf::validate + validation serveur (RG-T18) + allowlist (RG-T16)
|
||||||
|
| (action sensible) PinVerifier + throttle, audit_log dans la meme transaction
|
||||||
|
v
|
||||||
|
Repository -> PDO (prepared) -> MariaDB
|
||||||
|
|
|
||||||
|
v
|
||||||
|
Vue rendue dans admin/layout (sorties echappees, RG-T15) | ou JSON pour /api/*
|
||||||
|
```
|
||||||
|
|
||||||
|
La borne (kiosk) est servie en statique par Apache ; ses pages consomment les donnees
|
||||||
|
via `fetch` (JSON statique en P5 ; bascule sur `/api/*` DB-backed au swap P4).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Securite (security-by-design)
|
||||||
|
|
||||||
|
Couche transverse, regles `RG-T*` definies dans `docs/merise/mlt.md`. Synthese :
|
||||||
|
|
||||||
|
- **Authentification** : mot de passe hache **argon2id** (cout configurable, defauts
|
||||||
|
OWASP) ; sessions PHP avec regeneration d'ID au login, idle 4h + absolu 10h ; cookie
|
||||||
|
nomme `WAKDO_SID`.
|
||||||
|
- **RBAC** : `Authorizer::can(role_id, permission_code)` teste une **permission** (pas
|
||||||
|
un nom de role), rechargee depuis la base a chaque verification. 5 roles seedes, 23
|
||||||
|
permissions figees, matrice `role_permission` editable (back-office, voir domaine 10).
|
||||||
|
- **PIN d'action sensible (RG-T13)** : les operations sensibles (annulation, prix/TVA,
|
||||||
|
suppressions, inventaire, gestion utilisateur, RBAC, effacement PII) exigent une
|
||||||
|
re-autorisation par PIN equipier (argon2id). L'`acting_user_id` resolu par le PIN est
|
||||||
|
ecrit dans `audit_log` (RG-T14) dans la **meme transaction** que l'effet (RG-T08). Les
|
||||||
|
operations de stock tracent via `stock_movement.user_id` (pas de double-journal).
|
||||||
|
- **Throttling** (backoff degressif, pas de verrou definitif) :
|
||||||
|
- login par compte (`user.failed_login_attempts` / `lockout_until`) + par IP
|
||||||
|
(`login_throttle`, RG-8/9) ;
|
||||||
|
- PIN d'action sensible (`pin_throttle`, RG-T22) — compteur **separe** du login, par
|
||||||
|
utilisateur agissant.
|
||||||
|
- **Entrees / sorties** : validation serveur bornee (RG-T18) ; allowlist d'affectation
|
||||||
|
de masse (RG-T16, empeche d'injecter `role_id`/`price_cents`/`is_active`...) ; toutes
|
||||||
|
les sorties HTML echappees (RG-T15) ; front borne CSP-safe (pas de script inline cote
|
||||||
|
code projet).
|
||||||
|
- **Conventions HTTP** : conflit d'etat (unicite, FK RESTRICT) -> **409** ; validation
|
||||||
|
qui echoue -> **422** ; CSRF/permission -> **403**.
|
||||||
|
- **RGPD** : anonymisation (mlt 10.5) qui conserve la ligne (tombstone) pour preserver
|
||||||
|
les FK et la trace d'audit, en vidant la PII ; purges de retention par `wakdo-cron`
|
||||||
|
(audit_log, throttle, sessions, commandes).
|
||||||
|
- **Isolation** : pas de port hote en mode prod (acces par le proxy) ; user applicatif
|
||||||
|
MariaDB en moindre privilege (DDL reserve au runner migrate root ; cf.
|
||||||
|
`db/init/10-scope-app-user.sh`).
|
||||||
|
|
||||||
|
Threat model STRIDE + classification des donnees : `docs/PROJECT_CONTEXT.md` section 19.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Modele de donnees
|
||||||
|
|
||||||
|
22 tables (DDL `db/migrations/`), regroupees par domaine :
|
||||||
|
|
||||||
|
- **Catalogue** : `category`, `product`, `menu`, `menu_slot`, `menu_slot_option`,
|
||||||
|
`ingredient`, `product_ingredient`, `allergen`, `ingredient_allergen`, `stock_movement`.
|
||||||
|
- **RBAC / comptes** : `user`, `role`, `permission`, `role_permission`,
|
||||||
|
`role_visible_source`.
|
||||||
|
- **Commande (P4, schema pret)** : `customer_order`, `order_item`,
|
||||||
|
`order_item_selection`, `order_item_modifier`.
|
||||||
|
- **Transverses** : `audit_log` (journal immuable), `login_throttle`, `pin_throttle`.
|
||||||
|
|
||||||
|
Quelques derivations **calculees, non stockees** :
|
||||||
|
|
||||||
|
- **Stock en pourcentage** (mcd 5.3) : `stock_pct = round(stock_quantity / stock_capacity
|
||||||
|
* 100)` ; 3 bandes (normal / alerte / critique) selon `low_stock_pct` /
|
||||||
|
`critical_stock_pct`. `stock_quantity` est signe (survente assumee).
|
||||||
|
- **Disponibilite produit (RG-T21)** : un produit est commandable si `is_available = 1`
|
||||||
|
ET chaque ingredient non retirable de sa composition est au-dessus de la bande
|
||||||
|
critique. Pas de cascade ni de colonne stockee.
|
||||||
|
- **`service_day`** : journee de service (coupure a 10:00) pour les agregations stats,
|
||||||
|
expression SQL non materialisee.
|
||||||
|
|
||||||
|
MCD / MLD / dictionnaire : `docs/merise/`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Tests & qualite
|
||||||
|
|
||||||
|
- **PHPUnit** (`.phar`, sans Composer) : tests *unit* (controleurs via double
|
||||||
|
`FakeDatabase`, logique pure) + *integration* contre une vraie MariaDB (auto-skip si
|
||||||
|
`WAKDO_DB_TESTS != 1`). Lancement :
|
||||||
|
`docker run --rm -v "$PWD":/app -w /app wakdo-wakdo-app php phpunit.phar -c phpunit.xml`.
|
||||||
|
- **Front borne** : `node --test` + jsdom (`tests/js/`).
|
||||||
|
- **PHPStan niveau 6** (`.phar`).
|
||||||
|
- **CI Forgejo Actions** (`.forgejo/workflows/ci.yml`) : `secret-scan` (gitleaks),
|
||||||
|
`php-lint`, `static-tests` (PHPStan + PHPUnit avec service MariaDB ephemere migre +
|
||||||
|
seede), `js-tests` (Node 20), `auto-merge` (squash sur label + CI verte).
|
||||||
|
- **Branch protection** : `dev` et `main` proteges (PR requise, force-push bloque,
|
||||||
|
checks requis).
|
||||||
|
|
||||||
|
Pyramide visee : Unit > Integration > E2E. Les tests E2E navigateur (Playwright) sont
|
||||||
|
une initiative a venir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Methodologie & tracabilite
|
||||||
|
|
||||||
|
Projet developpe avec l'appui de **BYAN** (agents IA custom, Merise Agile + 64 mantras)
|
||||||
|
et d'outils d'IA generative, conformement a l'autorisation du centre de formation.
|
||||||
|
|
||||||
|
- Decisions d'architecture, scope et design : prises par l'auteur.
|
||||||
|
- Code, tests, doc : co-rediges et valides par l'auteur avant commit.
|
||||||
|
- **Pas de trailer `Co-Authored-By`** sur les commits : la transparence vit dans le
|
||||||
|
README et `docs/PROJECT_CONTEXT.md` section 17, pas dans les metadonnees git.
|
||||||
|
- Tracabilite : `docs/journal/` (retros par session et par feature).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Document vivant — mis a jour au fil de l'implementation. Source de verite scope/RNCP :
|
||||||
|
`docs/PROJECT_CONTEXT.md`.*
|
||||||
144
docs/DEVELOPER.md
Normal file
144
docs/DEVELOPER.md
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
# Guide developpeur — Wakdo
|
||||||
|
|
||||||
|
Comment lancer, tester et contribuer. Pour l'architecture (stack, services, modele,
|
||||||
|
securite), voir `docs/ARCHITECTURE.md`. Pour le scope et le mapping RNCP,
|
||||||
|
`docs/PROJECT_CONTEXT.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Prerequis
|
||||||
|
|
||||||
|
- Docker Engine + docker compose v2 (https://docs.docker.com/engine/install/).
|
||||||
|
- Node 20+ (uniquement pour les tests front borne ; pas requis pour faire tourner l'app).
|
||||||
|
|
||||||
|
Aucune installation de PHP / Composer / PHPUnit sur l'hote : tout passe par les
|
||||||
|
conteneurs et des `.phar` autonomes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Lancer en local
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
- Borne : http://kiosk.localhost:8080
|
||||||
|
- Admin + API : http://admin.localhost:8080
|
||||||
|
|
||||||
|
`*.localhost` resout vers `127.0.0.1`. Changer le port via `HTTP_PORT` dans `.env`.
|
||||||
|
Le `.env.example` fonctionne tel quel en local (valeurs dev). Au boot, le service
|
||||||
|
`wakdo-migrate` applique migrations + seed (admin bootstrap inclus) avant que l'app
|
||||||
|
ne serve.
|
||||||
|
|
||||||
|
Commandes utiles :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose ps # etat des services
|
||||||
|
docker compose logs -f wakdo-app # logs PHP-FPM
|
||||||
|
docker compose down # arret (volumes preserves)
|
||||||
|
docker compose down -v # arret + suppression des donnees
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploiement derriere un reverse proxy : voir le `README.md` (section prod) +
|
||||||
|
`docker-compose.prod.yml` (gitignore, propre a l'hote).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Base de donnees : migrations & seed
|
||||||
|
|
||||||
|
- `db/migrations/*.sql` (DDL) et `db/seeds/*.sql` (donnees de reference) sont appliques
|
||||||
|
de maniere **idempotente** par `wakdo-migrate` (suivi `schema_migrations` /
|
||||||
|
`seeds_applied`). Relancer `docker compose up` ne rejoue que les fichiers en attente.
|
||||||
|
- **Ajouter une migration** : creer `db/migrations/000N_description.sql` (ordre
|
||||||
|
lexicographique). Appliquee au prochain `docker compose up`, ou a la main :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash db/migrate.sh # applique les migrations en attente (hote)
|
||||||
|
bash db/migrate.sh --status # liste l'etat sans rien appliquer
|
||||||
|
```
|
||||||
|
|
||||||
|
- Idem pour un seed : `db/seeds/000N_description.sql`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Tests & analyse statique
|
||||||
|
|
||||||
|
Les tests PHP tournent dans l'image applicative (PHPUnit `.phar`). La stack doit etre
|
||||||
|
demarree pour les tests d'integration (ils ciblent le service `wakdo-db`).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Tests unitaires (sans base)
|
||||||
|
docker run --rm -v "$PWD":/app -w /app wakdo-wakdo-app \
|
||||||
|
php phpunit.phar -c phpunit.xml --testsuite unit
|
||||||
|
|
||||||
|
# Tests d'integration (vraie MariaDB ; auto-skip si WAKDO_DB_TESTS != 1)
|
||||||
|
docker run --rm --network wakdo_wakdo_internal --env-file .env -e WAKDO_DB_TESTS=1 \
|
||||||
|
-v "$PWD":/app -w /app wakdo-wakdo-app php phpunit.phar -c phpunit.xml
|
||||||
|
|
||||||
|
# Analyse statique PHPStan niveau 6
|
||||||
|
docker run --rm -v "$PWD":/app -w /app wakdo-wakdo-app \
|
||||||
|
php -d memory_limit=512M phpstan.phar analyse -c phpstan.neon --no-progress
|
||||||
|
```
|
||||||
|
|
||||||
|
Tests front borne (Node + jsdom) :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install # une fois (devDependency jsdom)
|
||||||
|
npm run test:js # node --test tests/js/
|
||||||
|
```
|
||||||
|
|
||||||
|
> Le nom de reseau `wakdo_wakdo_internal` et l'image `wakdo-wakdo-app` derivent du
|
||||||
|
> nom de projet compose (`name: wakdo`). Les `.phar` (phpunit, phpstan) sont
|
||||||
|
> gitignores ; les retelecharger si absents (voir `docs/journal/`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Conventions de code
|
||||||
|
|
||||||
|
- **PSR-4 manuel** : namespace `App\` -> `src/app/`. Pas de framework.
|
||||||
|
- **Controleurs** : non-`final` (seam de test ; les tests sous-classent et injectent
|
||||||
|
des doubles via `db()` / `sessionManager()`). Heritent de `AdminController`
|
||||||
|
(back-office) ou `AuthenticatedController`.
|
||||||
|
- **Acces donnees** : un repository par entite, dependant de `DatabaseInterface`
|
||||||
|
(PDO en prod, `FakeDatabase` en test). Requetes preparees uniquement.
|
||||||
|
- **Mutations** : CSRF (`Csrf::validate`) + validation serveur bornee (RG-T18) +
|
||||||
|
allowlist de colonnes (RG-T16). Sorties HTML echappees (RG-T15).
|
||||||
|
- **Actions sensibles** : PIN equipier (`PinVerifier`) + `audit_log` dans la meme
|
||||||
|
transaction ; throttle PIN (`PinThrottle`). Voir `docs/ARCHITECTURE.md` section 7.
|
||||||
|
- **Statuts HTTP** : conflit -> 409 ; validation -> 422 ; CSRF/permission -> 403.
|
||||||
|
- **Pas d'emoji** dans le code, les commits, les specs (Mantra IA-23).
|
||||||
|
|
||||||
|
Detail par entite : `docs/merise/` et `docs/domaines/` (a venir).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Git & CI
|
||||||
|
|
||||||
|
- **Conventional Commits** (anglais) : `type(scope): description` — types `feat`, `fix`,
|
||||||
|
`docs`, `refactor`, `test`, `chore`, `ci`, `db`, `perf`, `style`.
|
||||||
|
- **Branches** depuis `dev` : `feat/*`, `fix/*`, `docs/*`, `chore/*`, `ci/*`, `db/*`,
|
||||||
|
`refactor/*`, `test/*`. Merge vers `dev` par **PR squashee**. Periodiquement
|
||||||
|
`dev -> main` avec tag semver.
|
||||||
|
- **Auto-merge** : poser le label `auto-merge` sur la PR -> fusion automatique des que
|
||||||
|
la CI Forgejo est verte (secret-scan, php-lint, static-tests, js-tests).
|
||||||
|
Script : `scripts/forgejo-pr-automerge.sh`.
|
||||||
|
- **Pas de trailer `Co-Authored-By`** : la transparence sur l'usage de l'IA vit dans le
|
||||||
|
`README.md` et `docs/PROJECT_CONTEXT.md` section 17.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Ou trouver quoi
|
||||||
|
|
||||||
|
| Besoin | Emplacement |
|
||||||
|
|---|---|
|
||||||
|
| Architecture, stack, securite, modele | `docs/ARCHITECTURE.md` |
|
||||||
|
| Scope metier, planning, mapping RNCP | `docs/PROJECT_CONTEXT.md` |
|
||||||
|
| Modelisation Merise (dictionnaire, MCD/MCT/MLT, regles RG-T*) | `docs/merise/` |
|
||||||
|
| Decisions d'architecture (le pourquoi) | `docs/adr/` |
|
||||||
|
| Retros par session / feature | `docs/journal/` |
|
||||||
|
| Methodologie agents | `.claude/CLAUDE.md` + `.claude/rules/` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Document vivant — mis a jour au fil de l'implementation.*
|
||||||
Loading…
Add table
Reference in a new issue