corentin_wakdo/docs/SESSION_RESUME.md
Imugiii 6243304a29
Some checks failed
CI / secret-scan (push) Successful in 10s
CI / php-lint (push) Successful in 20s
CI / static-tests (push) Has been cancelled
CI / js-tests (push) Has been cancelled
feat(admin): page d'information RGPD sur le traitement des donnees (Cr 3.d.2)
2026-06-22 06:20:27 +00:00

94 KiB
Executable file
Raw Blame History

Session Resume — Wakdo

Document de reprise entre sessions de travail. A consulter en premier quand tu reprends le projet.


Derniere session : 2026-06-19 — Fix borne same-origin + GOAL re-alignement maquette (P5 front) + reste P4

Auteur : BYAN. Session marathon. Depart : le user a constate que la borne « n'etait pas cablee » (clic produit sans effet). Diagnostic prouve sur la vraie stack, puis un cycle FD complet (borne-realign-maquette, COMPLETED) + un /goal de 8 items livres en autonomie, chacun en PR auto-merge sur CI verte.

1. Fix borne same-origin (PR #62)

data.js faisait des fetch('/api/*') RELATIFS -> resolus sur l'origine borne (corentin-wakdo.stark.a3n.fr) ou il n'y a pas d'API -> fallback SPA index.html (HTML, pas JSON) -> catalogue vide. Le middleware CORS de #61 n'etait donc pas sollicite. Decision (secu + conventions) : SAME-ORIGIN. Le vhost kiosk relaie /api/* vers PHP-FPM (ProxyPassMatch + ProxyFCGISetEnvIf qui force SCRIPT_FILENAME sur admin/index.php, sinon FPM rejette via security.limit_extensions). CORS conserve en defense. conventions.md §10 reecrit.

2. Decomposition maquette (PR #63)

maquette-borne.pdf decompose : 10 ecrans en PNG (docs/design/screens/) + docs/design/ maquette-vs-build.md (mapping maquette<->build : la maquette est mono-ecran avec panneau persistant, le build etait multi-pages).

3. GOAL — 8 items livres (PR #64-#71)

  • #64 L1 : panneau commande persistant + bandeau categories + charte.
  • #65 L2 : composeur menu SLOT-DRIVEN /api/menus (remplace la compo libre ; ferme dette P4 #3).
  • #66 L3 : modale options produit (remplace la page product.html ; grille -> modales).
  • #67 seed : recettes des 53 produits (db/seeds/0003_ingredients_recipes.sql, 50 ingredients) -> stock vivant.
  • #68 L4 : SOUMISSION REELLE de commande (checkout.js panier->/api/orders create+pay) + ecran chevalet. Avant : checkout 100% simule.
  • #69 cleanup : memoisation des loaders data.js (promesse) + contraste a11y selection.
  • #70 orders admin : /admin/orders (order.read) + KPIs vente dans /admin/stats (OrderQueryRepository).
  • #71 /api/allergens : endpoint public (id/code/name) ; la borne garde son JSON statique (descriptions). Item 0 = gate CI js-tests requis (dev+main).

Decouvertes corrigees

  • La borne ne soumettait aucune commande (payment.html simulait) -> soumission reelle cablee.
  • Migration 0003_order_service_tag.sql non appliquee sur la stack dev (3 j d'uptime) -> la creation de commande echouait (Unknown column service_tag). Reconciliee dans schema_migrations ; doublon de migration ecarte (catch d'une revue adversariale).
  • Incident compose (reseau recree) : wakdo-web recree via docker compose -f docker-compose.prod.yml up -d --no-deps --force-recreate (la stack tourne via prod.yml + Traefik reseau admin_proxy).

Verification

351 tests PHP (unit + integration DB) + 64 JS, PHPStan L6 propre. e2e reel : commande K1 creee + payee, stock decremente exactement (-5 Steak hache). Chaque lot a eu une revue adversariale par workflow (must-fix integres).

Nettoyage git (fin de session)

Branches purgees : local + forge = dev + main seulement (17 branches feature mergees supprimees cote forge, 6 locales). dev = 7ab9a5a (#71).

EN COURS — accompagnement menu Frite/Potatoes + Maxi (approuve, NON code)

Le user a constate que le composeur menu propose les 5 produits frites (Petite/Moyenne/ Grande Frite + Potatoes/Grande Potatoes) comme accompagnement. Regle voulue (et conforme maquette ecran 4 : 2 choix Frites/Potatoes) :

  • Menu = 2 choix d'accompagnement : Frites (Moyenne Frite) + Potatoes.
  • Maxi -> version Grande associee automatiquement (Grande Frite / Grande Potatoes).
  • Petite Frite + tailles individuelles = a la carte seulement (section frites), hors menu.

Approche choisie par le user : variante en base (data-driven, le stock decremente le bon produit). Plan a executer (TDD + revue + commit/PR/auto-merge) :

  1. Migration db/migrations/0004_product_maxi_variant.sql : ALTER TABLE product ADD COLUMN maxi_variant_product_id INT UNSIGNED NULL + FK -> product(id). A appliquer sur dev.
  2. Seed db/seeds/0004_menu_side_maxi.sql (idempotent) :
    • UPDATE product SET maxi_variant_product_id=24 WHERE name='Moyenne Frite' (24 = Grande Frite) ; =26 WHERE name='Potatoes' (26 = Grande Potatoes).
    • DELETE des options de slot side pour ne garder que Moyenne Frite (23) + Potatoes (25) ; retirer Petite Frite (22), Grande Frite (24), Grande Potatoes (26) des options menu.
  3. ProductRepository::find (src/app/Catalogue/ProductRepository.php:50) : ajouter maxi_variant_product_id aux colonnes du SELECT (absent aujourd'hui).
  4. OrderRepository::resolveSelections (src/app/Order/OrderRepository.php:395) : passer le format ; valider la selection BASE contre les options du slot, puis si format='maxi' ET le produit a un maxi_variant non nul -> STOCKER l'id de la variante (label de la variante). consumption() decremente alors la Grande variante (stock correct). resolveLine (qui connait le format) passe $format a resolveSelections.
  5. Tests : OrderRepository DbTest (menu Maxi + accompagnement -> selection stockee = Grande variante + stock decremente Grande Frite, pas Moyenne) ; unit du swap dans resolveSelections.
  6. Borne : le composeur affiche 2 options automatiquement (slots /api/menus restreints par le seed) -> pas de code borne. Afficher le libelle Maxi au recap = optionnel, differable.

Ids frites (dev) : Petite 22, Moyenne 23, Grande 24, Potatoes 25, Grande Potatoes 26.

Reste / a faire

  • VALIDATION VISUELLE utilisateur sur ecran reel (gros changement front, pas encore vu en vrai).
  • Differes (LOW, notes) : format menu deduit de supplement_cents (theorique, seed +150) ; multi-slots de meme slot_type (menus famille) ; descriptions allergenes cote schema si on veut basculer la borne sur /api/allergens.
  • Donnees demo : commande de test K1 en base dev (stock -5, sans impact).

Reprendre

cd /home/acadenice/corentin_wakdo
git checkout dev && git fetch forgejo && git merge --ff-only forgejo/dev
git log --oneline -12 dev   # #62 fix borne ... #71 allergens
docker compose ps           # stack dev (prod.yml + Traefik)

Session : 2026-06-18 (suite 2) — P4 read API borne (#60) + cablage CORS/data.js (#61)

Auteur : BYAN. Deux cycles FD menes en entier (BRAINSTORM -> PRUNE -> DISPATCH -> BUILD -> VALIDATE), chacun livre en PR auto-merge sur CI verte. But : brancher la borne kiosk sur le catalogue en base, a la place des fichiers JSON statiques.

Livre

  • PR #60 — read API catalogue borne (mergee dans dev, squash a35db88) : 5 endpoints publics anonymes en lecture seule (docs/api/conventions.md 5.2) : GET /api/categories, /api/products, /api/products/{id}, /api/menus, /api/menus/{id} (detail avec slots). CatalogueController + methodes de lecture filtrees sur Category/Product/MenuRepository (is_available=1 ET categorie active : la borne ne voit que le commandable, en liste comme en detail). Enveloppe {data,total}, champs canoniques snake_case ; vat_rate exclu, is_available retire des payloads, is_required de slot en booleen, sans timestamp. Dispo calculee RG-T21 differee (recettes non seedees).
  • PR #61 — cablage borne (CORS + data.js) (auto-merge arme a la redaction) :
    • App\Core\Cors : middleware CORS scope /api/, origine unique et exacte (CORS_ALLOWED_ORIGIN, sans joker), GET/POST/OPTIONS, header Content-Type, sans credentials, fail-closed ; preflight OPTIONS -> 204 avant le routeur ; decoration de la reponse y compris le 500 du catch. CORS_ALLOWED_ORIGIN deja cable (.env.example + docker-compose).
    • data.js reecrit : consomme /api/categories|products|menus, deballe {data}, traduit la forme canonique vers la forme borne (nom/prix/image/type), regroupe par slug de categorie, glisse les menus sous la cle menus. Signatures publiques inchangees -> pages intactes. loadAllergens reste statique.

Revue adversariale (workflow multi-agents, une par cycle)

  • Read API : 1 finding LOW (lacune de test : slot sans option) -> test ajoute.
  • Cablage : 2 findings, corriges.
    • CRITIQUE : findProduct(id) supposait des ids uniques sur l'ensemble du catalogue (vrai pour l'ancien JSON statique). En base, product et menu sont deux tables auto-increment distinctes demarrant a 1 -> collision (id 4 = burger Big Mac ET Menu Big Mac), cliquer un burger ouvrait le composeur de menu. Corrige : findProduct(id, categorySlug) desambigue par categorie (id unique dans une categorie) ; page-product.js passe le slug deja present dans l'URL ; 2 tests de regression.
    • LOW : la reponse 500 du catch n'etait pas decoree CORS -> $request/$cors construits hors du try + decoration de la 500.

Etat tests / CI

PHP unit 305 / 859 assertions, integration 40 / 253 (WAKDO_DB_TESTS=1, vraie base dev), PHPStan L6 propre ; JS data.js 10 tests (node:test, fetch mocke). CI Forgejo : merge natif squash sur checks requis (secret-scan, php-lint, static-tests).

Decisions actees

  • L'API de lecture parle le dictionnaire (snake_case canonique) ; le rapprochement vers la forme heritee de la borne se fait en un point unique, data.js (conventions.md 8.3).
  • Le composeur de menu reste libre (il ne consomme pas les slots /api/menus) pour ce chunk ; sa refonte sur les slots est differee.
  • Regle de livraison (user) : livrer via commit + PR + auto-merge natif sur CI verte, sans gate manuel a chaque commit (memoire feedback_commit_discipline).

File d'attente (suite)

  1. Verif cross-origin reelle : le .env pointe CORS_ALLOWED_ORIGIN sur l'origine serveur. Pour valider borne -> API en local, mettre CORS_ALLOWED_ORIGIN sur l'origine du kiosk (APP_URL_KIOSK) + recreer wakdo-app, puis E2E #45.
  2. Seed des recettes (product_ingredient) -> active le decrement de stock de pay() (chunk 1b) ET la dispo calculee RG-T21 dans les endpoints read.
  3. Refonte du composeur de menu borne pour consommer les slots /api/menus (B1 burger impose, B2 Normal/Maxi) au lieu de la composition libre.
  4. Gate CI : ajouter CI / js-tests aux checks requis (sinon un JS rouge pourrait merger).
  5. Optionnel : /api/allergens (la borne garde son JSON), prix en euros vs centimes.

Reprendre

cd /home/acadenice/corentin_wakdo
git checkout dev && git fetch forgejo && git merge --ff-only forgejo/dev
git log --oneline -6 dev   # #60 read API + #61 cablage borne
docker compose up -d

Session : 2026-06-17 (suite) — P3 Users/RBAC/Stats + Makefile -> docker compose

Auteur : BYAN. Deuxieme cycle FD du jour (20260617-102548-p3-users-rbac-stats, COMPLETED) puis un chore d'infra. P3 back-office desormais complet.

Livre (dev = 9d75fab)

  • Lot S — Stats (#37) : StatsController + StatsRepository -> /admin/stats (permission stats.read). KPIs disponibles : compteurs catalogue + sante stock (bandes RG-T21). Ferme le 404 du landing manager. KPIs de vente differes P4.
  • Lot U — Users (#38) : UserController + UserRepository (mlt domaine 10). CRUD comptes, desactivation, anonymisation RGPD (mlt 10.5, tombstone). Chaque mutation = PIN equipier + audit (RG-T13/14), throttle (RG-T22). Garde-fous : pas d'auto-desactivation (403), dernier admin actif protege. Unicite email -> 409.
  • Lot R — RBAC (#39) : RoleController + RoleRepository (mlt 10.4). Matrice roles x permissions (cases scalaires perm_<id>) + roles custom (RG-4) + role_visible_source. PIN + audit avec DIFF des permissions (RG-6). Garde admin (garde role.manage + reste actif), code immuable, 409 code dupli.
  • Chore (#40) — Makefile -> docker compose up : service one-shot wakdo-migrate (image mariadb) applique migrations (suivi schema_migrations) + seed (suivi seeds_applied) idempotents via db/migrate-container.sh (connexion reseau) ; wakdo-app/web attendent sa completion. Makefile supprime. Le « une commande » (Cr 7.c.4) passe de make init a docker compose up. Cr 7.b porte par les scripts Bash. Docs realignees + correction CI = Forgejo Actions (pas GitHub). Detail : docs/journal/2026-06-17--makefile-to-compose-migrate.md.
  • Chore (#41) — docker-compose.yml standalone portable : le repo ship un compose qui tourne EN LOCAL sans config (docker compose up -d -> http://kiosk.localhost:8080
    • http://admin.localhost:8080), facon app open-source. Reseau interne seul, wakdo-web publie ${HTTP_PORT:-8080}:80, plus de Traefik dans le fichier versionne, zero commentaire. Renommage TRAEFIK_DOMAIN_* -> APP_HOST_KIOSK/ADMIN (vhosts Apache ServerName, *.localhost en local). .env.example local-first (valeurs dev qui marchent sans edition). Prod = docker-compose.prod.yml GITIGNORE, propre a chaque hote (meme stack + Traefik, sans port hote) : docker compose -f docker-compose.prod.yml up -d. Valide via docker compose config (les deux fichiers) ; smoke-test runtime a faire sur machine propre (container_name fixes -> pas de up parallele a la stack en cours).
  • Doc set socle (#42/#43/#44) : docs/ARCHITECTURE.md (10 sections) + docs/DEVELOPER.md (#42) ; docs/adr/ (index + 9 ADR : from-scratch, MVC serveur, stock %, PIN+audit, throttle PIN, 409/422, RGPD anonymise, Makefile->compose, standalone+prod) (#43) ; docs/domaines/ (index + 7 fiches : auth, catalogue, stock-recettes, users, rbac, stats, borne) (#44). Decoupage en 3 PR par cohesion (squash). A pousser/lire sur la Forge.

Etat tests / CI

unit 263 + integration 301/916 assertions (WAKDO_DB_TESTS=1) + 7 tests JS + 2 parcours E2E (borne + admin, Playwright, lance a la main), PHPStan L6, CI Forgejo verte. Branches feature nettoyees (local + remote).

Fait depuis

  • Smoke-test standalone : PASSE (2026-06-17). Lance dans un projet jetable isole (-p wakdotest, override container_name, port 8099) pour ne pas toucher la stack dev 26h : migrate exit 0 (2 mig + 2 seeds, 5 roles/23 perms/admin), borne kiosk.localhost HTTP 200 (<title>Wakdo - Bienvenue</title>), admin admin.localhost HTTP 200 (Wakdo back-office), healthz 200. Le renommage APP_HOST_* marche au runtime. Projet jetable + volumes/images supprimes ensuite.
  • .env LOCAL migre : TRAEFIK_DOMAIN_* -> APP_HOST_* (memes valeurs FQDN). Le .env SERVEUR reste a migrer (idem) avant son prochain deploiement.
  • Playwright E2E etape 1 : PASSE (#45, dev). Parcours borne complet (welcome -> boissons -> produit -> ajout panier -> panier -> paiement -> confirmation), headless en conteneur officiel, contre une stack JETABLE isolee (tests/e2e/run.sh). A trouve + corrige un bug a11y : #pay-btn (un <a>) gardait aria-disabled="true" car .disabled est un no-op sur un <a> -> pilote via aria-disabled (commit 2b51be3). Detail conteneur : hostnames de test en .test (Chromium force *.localhost->127.0.0.1).
  • Playwright E2E etape 2 : PASSE (#46, dev). Parcours admin : garde -> login (admin@wakdo.local / mdp dev seede + CSRF) -> /admin/dashboard -> logout. A revele un probleme secu/usage : cookie de session secure=true en dur -> session intenable en HTTP local -> login admin KO. Corrige en secure conditionnel au HTTPS (SessionManager::cookieSecure, X-Forwarded-Proto ; prod inchange) -> ADR-0010. Valide : PHPStan L6, 263 unit, 2 E2E verts.

File d'attente (decidee avec le user)

  1. Deploiement serveur (Thanos) : migrer le .env serveur (TRAEFIK_DOMAIN_* -> APP_HOST_*, memes valeurs ; HTTP_PORT inutile en prod), placer son docker-compose.prod.yml (gitignore), back-fill seeds_applied avant le 1er up avec wakdo-migrate (sinon re-seed -> conflits). Le .env local est deja migre.
  2. Playwright E2E — etape 3 (CI) : etapes 1 (borne) + 2 (admin) FAITES. Reste le job CI Forgejo qui monte la stack jetable + lance Playwright en conteneur (image mcr.microsoft.com/playwright:v1.49.1-jammy, doit matcher la devDep). NB : le runner CI doit pouvoir faire du docker-in-docker / acceder au socket (a verifier).
  3. Front : page de LOGIN a retravailler (demande user : "la page login est moche"). Initiative UI dediee ; ne PAS confondre avec le dashboard admin (qui, lui, va).
  4. Doc set — suite possible : diagrammes/captures, ou doc commande quand P4 sort. Footgun : branches docs/* heurtent le dossier docs/ dans forgejo-pr-automerge.sh (git log "$HEAD" ambigu) -> passer le titre en 3e arg.
  5. Reste P4 : domaine commande (KPIs vente, liens nav orders, swap borne->API).

Reprendre

cd /home/acadenice/corentin_wakdo
git checkout dev && git fetch forgejo && git merge --ff-only forgejo/dev
docker compose up -d   # stack complete en une commande (migrate+seed via wakdo-migrate)

Session : 2026-06-17 — P3 Stock + Recettes + Borne allergenes (cycle FD complet, 4 PR mergees)

Auteur : BYAN. Cycle FD 20260616-134152-p3-ingredients-stock mene a terme (reprise a DISPATCH -> BUILD -> VALIDATE). Scope Stock + recettes, etendu en cours a la borne allergenes, livre en 4 PR sequentielles toutes mergees sur dev en auto-merge sur CI verte.

Livre (dev = 1ecd783)

  • PR-0 #33 — Harmonisation HTTP 409 : les reponses de CONFLIT (SQLSTATE 23000 : unicite + hard-delete bloque par FK RESTRICT) passent de 422 a 409 sur Category/Product/Menu (aligne le code sur le contrat byan-api.md) ; la validation simple reste 422. IngredientController nait directement en 409.
  • PR-A #34 — Stock ingredients : IngredientRepository (CRUD, stock %/bande calcules, restock tx, inventoryCount tx ecrivant 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 equipier, pin.failed+throttle en 1 tx, sans audit_log au succes RG-T14 ; movements stock.read, user_id visible manager/admin RG-4) ; vues admin/ingredients/* + lien nav Stock ; hard-delete bloque -> 409.
  • PR-B #35 — Recettes + dispo calculee : ProductRepository (composition, setComposition delete-and-reinsert tx, ingredientExists, compositionCount, autoUnavailableIds, isOrderable RG-T21) ; editeur recette ProductController::recipeForm/saveRecipe (ingredient.manage, sans PIN) + vue admin/products/recipe.php + product-recipe.js (vanilla CSP-safe) ; badge "Rupture auto" (RG-T21) dans la liste produits ; dette #27 fermee (nb de lignes product_ingredient cascade-supprimees trace dans le resume d'audit a la suppression produit).
  • PR-C #36 — Borne allergenes : icone "i" sur carte ET fiche produit ouvrant une modale GENERALE des 14 allergenes INCO (allergens.js CSP-safe, data/allergens.json, loadAllergens() dans data.js avec point de swap P4 -> /api/allergens). Premier harnais de tests front du depot : node:test + jsdom (tests/js/, 7 tests), job CI js-tests (Node 20 epingle via NodeSource).

Decisions actees (2026-06-17)

  • Inventaire = seule action sensible du domaine stock (RG-T13 liste 9.2, hors 8.8 CRUD et 9.1 restock). Succes -> stock_movement.user_id, sans audit_log (RG-T14). Echec PIN -> pin.failed + throttle dans UNE transaction (RG-T22).
  • "i" allergenes = info GENERALE (14 INCO), pas un calcul par produit. Mapping ingredient_allergen et allergenes calcules par produit restent differes.
  • Harnais JS : ESM declare LOCALEMENT (src/public/borne/assets/js/package.json + tests/js/package.json), racine en CommonJS -> hooks .claude / _byan / bin intacts. (Une 1ere tentative "type":"module" a la racine cassait les hooks CommonJS -> corrige avant commit.)

Etat tests / CI

259 tests PHP / 777 assertions (WAKDO_DB_TESTS=1), PHPStan L6 propre ; 7 tests JS (node:test + jsdom). CI dev verte : secret-scan, php-lint, static-tests, js-tests.

A faire (suivi)

  • Gate CI : ajouter CI / js-tests (pull_request) aux checks REQUIS de la branch protection (scripts/forgejo-branch-protection.sh). Au merge de #36 l'auto-merge natif (merge_when_checks_succeed) n'a pas attendu js-tests (pas encore requis) ; il a valide a posteriori sur dev (vert). Sans ce gate, une PR au JS rouge pourrait merger.
  • P3 restant : Users + matrice RBAC ; Stats (ferme le finding manager.default_route = /admin/stats 404).
  • Differe : mapping ingredient_allergen + allergenes calcules par produit ; decrement atomique RG-T20 + swap borne JSON->API = domaine commande P4 (debloque liens nav orders #23, purge ORDER_RETENTION #25).
  • Hygiene user : vars .env auth/throttle absentes (l'app tourne sur ses defauts code) ; revoquer anciens PAT GitHub.

Reprendre

cd /home/acadenice/corentin_wakdo
git checkout dev && git fetch forgejo && git merge --ff-only forgejo/dev
git log --oneline -6 dev
# FD p3-ingredients-stock en phase VALIDATE (a clore en COMPLETED apres validation finale).

Session : 2026-06-16 — Audit "du reel" + 13 PR de remediation + Menus (#32) + demarrage Ingredients/stock

Vue d'ensemble

Session longue, quatre temps :

  1. Diagnostic branche dev (CI "rouges" + graphe "bizarre").
  2. Audit sur pieces du travail du 2026-06-15 (demande : "du reel, pas le journal") via un sweep multi-agents + verification adversariale -> 13 PR de remediation, toutes mergees.
  3. Feature Menus construite en cycle FD complet (PR #32, mergee).
  4. Demarrage du cycle FD Ingredients/stock -> EN PAUSE a la phase DISPATCH.

1. Diagnostic dev (resolu, rien de casse)

  • "CI pas vertes" = 8 echecs auto-merge cosmetiques (double-fire : un 2e run tente de merger une PR deja mergee -> non-200 ; job non-bloquant) + 3 static-tests historiques (PR #9, php-xml/mbstring manquants, corriges le jour meme). dev HEAD etait vert.
  • "Graphe bizarre" = refs de suivi locales non prunees (branches squash-mergees, supprimees cote serveur). git fetch --all --prune nettoie. Le squash ne cree pas de 2e parent -> moignons rouges (cosmetique).

2. Audit + remediation (PR #19-#31, toutes mergees)

  • CRITIQUE : durcissement php.ini absent du conteneur en service (image perimee) -> rebuild wakdo-app (runtime, fait + verifie).
  • HIGH : la CI ne lancait aucun test d'integration DB (auto-skip) -> #21 (service MariaDB + WAKDO_DB_TESTS=1 + --fail-on-skipped).
  • MEDIUM : XSS kiosk innerHTML #20 ; liens nav morts #23 ; user DB GRANT ALL -> moindre privilege #24 ; purge RGPD/throttle cron #25.
  • LOW : enum email sur reset #26 ; contrat FK suppression produit #27 ; lien page PIN #28 ; bouton mort PASSWORD_ALGO #29 ; atomicite chemin echec PIN #30 ; drift JSON borne #31.
  • + maquettes .html non authentifiees retirees #19 ; note d'audit jury docs/journal/2026-06-16--audit-reel-livrables-p2-p3.md #22.
  • Incident : docker compose up -d <service> nu a tue le reseau (vars ${...} absentes du .env -> drift) -> recup down+up sans perte. Memoire ops-compose-single-service-network (utiliser --no-deps --force-recreate).

3. Menus (PR #32, mergee)

CRUD menus composes (mlt 8.4-8.6) : burger de base + slots (menu_slot/menu_slot_option), prix Normal/Maxi. Slots en vanilla JS (champ cache slots_json, CSP-safe). delete = PIN equipier + audit ; create/update sans PIN ; update = delete-and-reinsert des slots. Lien nav Menus reactive. Acces : menu.create/update admin+manager, menu.delete admin seul, menu.read tous.

Etat Git

dev = c2a4854 (toutes les PR #19-#32 mergees ; local == forgejo == github). Working tree propre sur dev. Branches feature supprimees au merge. 201 tests verts (597 assertions avec WAKDO_DB_TESTS=1), PHPStan L6 propre, CI verte (avec tests d'integration DB).

4. EN COURS : FD Ingredients/stock (PAUSE a DISPATCH)

  • fd_id = 20260616-134152-p3-ingredients-stock, phase DISPATCH (voir byan_fd_status).
  • Scope decide : Stock + recettes, livre en 2 PR sequentielles :
    • PR-A Stock : IngredientRepository (CRUD + calcul stock %/bande + restock tx + inventoryCount tx + registre stock_movement + isReferenced) ; IngredientController (CRUD ingredient.manage ; RESTOCK stock.manage ; INVENTORY_COUNT stock.count + PIN ; mouvements stock.read) ; vues admin/ingredients/{index,form,restock,inventory,movements} + lien nav Stock ; tests (unit + integration + FakeDatabase).
    • PR-B Recettes : product_ingredient (quantite normal/maxi, is_removable/is_addable, extra_price_cents), editeur imbrique facon slots (vanilla JS). Debloque RG-T21 (dispo produit calculee) + ferme la dette #27 (trace cascade).
  • Decisions actees : inventaire = PIN + trace stock_movement.user_id SANS audit_log (RG-T14 exclut le stock du double-journal) ; soft-delete is_active, hard-delete bloque (FK product_ingredient/stock_movement RESTRICT -> 422).
  • Modele : ingredient (stock_quantity signe ; stock_capacity>0 = 100% ; pack_size ; low_stock_pct=10/critical_stock_pct=5 avec critical<low) ; stock_movement append-only (sale/cancellation/restock/inventory_correction).
  • Permissions : ingredient.manage + stock.manage = admin+manager ; stock.count + stock.read = tous les roles.
  • A LA REPRISE : dire "go PR-A" -> chunk 1 = IngredientRepository + IngredientRepositoryDbTest (meme decoupe que Menus, chaque chunk verifie).

A faire (apres le stock)

  • P3 restant : Users + matrice RBAC ; Stats (ferme le finding manager.default_route = /admin/stats 404).
  • Differe : allergenes ingredient_allergen ; affichage dispo calculee RG-T21 (vient avec PR-B) ; domaine commande P4 (debloque les liens nav orders #23, la purge ORDER_RETENTION #25).
  • Hygiene cote user : les vars auth/throttle (ARGON2_*, ACCOUNT_LOCKOUT_*, PIN_THROTTLE_*, ...) sont absentes du .env reel (l'app tourne sur ses defauts code) ; revoquer les anciens PAT GitHub.

Reprendre

cd /home/acadenice/corentin_wakdo
git checkout dev && git fetch forgejo && git merge --ff-only forgejo/dev
git log --oneline -6 dev
# FD en cours : phase DISPATCH. Dire "go PR-A" pour reprendre le build (IngredientRepository).

Session : 2026-06-15 (suite 5) — P3 : throttle PIN (RG-T22, #18) merge

Vue d'ensemble

Fermeture du finding HIGH de la revue Produits (PIN d'action sensible sans limitation de tentatives). Conception via un panel multi-agents (3 lentilles Ockham / efficacite-menace / anti-DoS -> synthese -> passe adversariale, holds = true), construction en TDD avec les correctifs de l'adversaire integres, revue adversariale de l'implementation (holds = true), puis merge sur dev en auto-merge (PR #18).

Resume de session detaille (format jury RNCP) : docs/journal/2026-06-15--p3-throttle-pin-rg-t22.md.

Decision actee

Compter les echecs de PIN par utilisateur AGISSANT ($guard->userId), pas par email cible (contournable par rotation) ni par IP (collateral sur poste a session partagee). Table dediee pin_throttle (entite 22) cle sur actor_user_id (FK ON DELETE CASCADE), separee des compteurs de connexion : un echec de PIN n'incremente aucun compteur de login (pas d'escalade DoS). Bornes propres (PIN_THROTTLE_*, base 30s / plafond 300s, plus permissives que le login : controle de dissuasion).

Ce qui a ete livre (merge ; PR #18 ; dev = ad5203d)

  • App\Auth\PinThrottle (isLocked / recordFailure upsert atomique + backoff / reset), dimension 'pin' de ThrottlePolicy, PinVerifier::payTimingDecoy (parite de timing), cablage ProductController update/destroy (gate avant verification, pas de pin.failed sous verrou actif = anti-flood, reset sur l'acteur de session).
  • Migration 0002_pin_throttle.sql (appliquee a la base dev) ; docs Merise 21 -> 22 entites (RG-T22) ; .env.example + docker-compose.yml (PIN_THROTTLE_*).
  • 188 tests verts (525 assertions), PHPStan L6 propre. Branche supprimee (local + remote).

Etat Git

dev   ad5203d   (auth #11 ... produits #17 + throttle PIN #18 ; local == forgejo == github)
Hors-scope untracked : package*.json, SESSION_RESUME.md, journal P1 2026-06-04.

A faire a la reprise

  • Suite P3 : Menus (+ slots), Ingredients/stock, Users + matrice RBAC, Stats.
  • Differe : etendre le cron de purge a pin_throttle (predicat dans mlt.md 13.5) ; alerte de volume pin.failed cote supervision ; seed ingredients/recettes ; revoquer anciens PAT GitHub.

Reprendre

cd /home/acadenice/corentin_wakdo
git checkout dev && git fetch forgejo dev && git merge --ff-only forgejo/dev
git log --oneline -8 dev

Session : 2026-06-15 (suite 4) — P3 : CRUD Produits (#17)

Vue d'ensemble

Suite directe de la session P3. Le CRUD Produits est livre et merge (PR #17, squash sur dev), memes patterns que Categories : App\Catalogue\ProductRepository sur DatabaseInterface, ProductController non-final, double FakeDatabase, tests unit + integration auto-skippee, revue adversariale par chunk. C'est le premier usage reel du PIN d'action sensible (RG-T13) sur des mutations metier, avec ecriture audit_log dans la meme transaction (RG-T08 / RG-T14).

CRUD Produits (merge ; PR #17 ; dev = 2756fb4)

  • App\Catalogue\ProductRepository (DatabaseInterface) : all/find/create/update/delete + categoryExists, allowlist de colonnes a l'ecriture (RG-T16).
  • ProductController (index/create/store/edit/update/confirmDelete/destroy) : chaque action guard('product.manage') (RG-T03), mutations CSRF (RG-T01), validation serveur bornee (RG-T18 : categorie existante, nom <=120, prix > 0 et <= UINT32, TVA dans {55,100}, image <=255, display_order 0..65535).
  • PIN conditionnel (8.2 RG-4) : a l'update, le PIN equipier est exige uniquement si price_cents OU vat_rate change (les deux sont fiscalement sensibles : sur_place 10% vs a_emporter 5.5%) ; sinon write simple sans PIN. A la suppression, le PIN est exige dans tous les cas.
  • Modele PIN = identifiant equipier + PIN : PinVerifier::resolveActingUser(email, pin) (ajoute ce chunk) resout l'identite de l'equipier qui valide (SELECT filtre is_active = 1), et c'est cet acting_user_id (pas l'utilisateur de session) qui est ecrit dans audit_log (RG-T14), dans la MEME transaction que la mutation (RG-T08).
  • Suppression FK-safe : hard delete seulement si le produit n'est pas reference (order_item / menu.burger_product_id, FK RESTRICT) ; sinon PDOException SQLSTATE 23000 traduit en 422.
  • Vues admin/products/{index,form,delete}, ajout des routes dans src/public/admin/index.php.
  • 172 tests verts (452 assertions), PHPStan L6 propre.

Revue : 6 findings confirmes (0 refute)

  • HIGH — PIN d'action sensible sans limitation de tentatives. PinVerifier verifie avec parite de timing (leurre argon2id) mais sans compteur ni backoff : un insider tenant deja product.manage peut iterer les PIN (4 chiffres = 10^4) contre l'email d'un collegue et forger l'acting_user_id de l'audit. Le login a son login_throttle (RG-8) ; le PIN n'a pas d'equivalent. Mitigation shippee dans ce chunk : chaque PIN refuse ecrit un audit_log pin.failed (acteur NULL, cible, email tente) -> la tentative devient detectable et alertable. Le throttle PIN degressif complet reste a faire (chunk dedie, cf. plus bas).
  • LOW — case is_available : sur re-rendu d'erreur, une case decochee revenait cochee (fallback ?? 1 applique aussi au re-rendu). Corrige : la valeur ne retombe sur le defaut que pour le formulaire de creation, le re-rendu reflete l'etat soumis.
  • 4 MEDIUM = lacunes de couverture / resistance aux mutations (le code de prod etait correct, les correctifs durcissent les tests) :
    • chemin TVA-only (vat 55) non teste -> ajout testUpdateVatChangeRequiresPin + ...WithValidPinAudits.
    • route resolveActingUser du FakeDatabase ne forcait pas is_active = 1 (un mutant retirant le predicat passait) -> route durcie + assertion SQL.
    • test de suppression n'assertait pas que l'acteur audit = l'equipier resolu -> assertions actor (uid === 9, rid === 4) ajoutees sur update et destroy.
    • FakeDatabase ne prouvait pas que l'INSERT audit_log tombe ENTRE begin et commit (deux listes disjointes) -> ajout d'un eventLog entrelace + assertions d'ordre (begin < audit < commit).

Etat Git (post-chunk)

dev   2756fb4   (auth #11 + RBAC #12 + PIN #13 + shell #14 + categories #15 + set-PIN #16 + produits #17 ; == forgejo/dev)
Branche feat/p3-products-crud supprimee (remote auto-merge + local). 172 tests, PHPStan L6 propre.
Hors-scope untracked : package*.json, SESSION_RESUME.md, journal P1.

A faire a la reprise — d'abord le throttle PIN (chunk dedie), AVANT Menus / Stock

  • Throttle PIN d'action sensible (chunk dedie, prioritaire) : fermer le finding HIGH. Decision de schema a trancher d'abord : ne PAS reutiliser les colonnes user.failed_login_attempts / lockout_until du login (un attaquant qui spamme le PIN d'une victime verrouillerait son LOGIN = DoS sur la victime). Pistes : compteur PIN dedie (colonnes pin_failed_attempts / pin_lockout_until sur user, OU table pin_throttle), dimension per-user ET per-IP (comme RG-8), reponse generique (ne pas reveler quels emails existent), reset sur succes. Reutilise ThrottlePolicy. Ajouter une RG Merise dediee + migration + tests. La mitigation pin.failed reste en place entre-temps.
  • Ensuite : Menus (+ slots), Ingredients/stock, Users + matrice RBAC, Stats.
  • Differe : seed ingredients/recettes ; revoquer anciens PAT GitHub.

Reprendre

cd /home/acadenice/corentin_wakdo
git checkout dev && git fetch forgejo dev && git merge --ff-only forgejo/dev
git log --oneline -7 dev

Session : 2026-06-15 (suite 3) — P3 : shell (#14) + CRUD Categories (#15) + set-PIN (#16)

Vue d'ensemble

P3 (CRUD admin) demarre. Architecture tranchee : pages rendues serveur (PHP MVC), pas d'API JSON pour le back-office (coherent avec l'auth, demontre le MVC). Routes back-office sous /admin/... (le seed fixe role.default_route a /admin/dashboard, /admin/stats, etc.). Deux chunks merges, memes patterns que P2 (services/repos sur DatabaseInterface, controleurs non-final, FakeDatabase, tests unit + integration auto-skippee, revue adversariale par chunk).

Shell admin (merge ; PR #14)

  • Controller gagne un hook layoutName() (defaut inchange) ; le back-office rend dans admin/layout.
  • AdminController (base) : guard(permission?) = RG-6/RG-T02 (302 /login si session KO) puis RG-T03 (403 si permission manquante), sinon GuardResult ; adminView() injecte identite + permissions + CSRF + flash ; helpers setFlash/takeFlash.
  • DashboardController -> GET /admin/dashboard ; UserDirectory (nom + libelle role topbar).
  • Vues admin/{layout,dashboard,forbidden} : nav conditionnee aux permissions, logout POST CSRF, sorties echappees (RG-T15). Premier cablage reel du SessionGuard sur une page.
  • Revue : 5 findings corriges (initiales multibyte, couverture 403, test d'echappement, marqueur de fragment, commentaire d'heritage).

CRUD Categories (merge ; PR #15) — pattern de reference

  • App\Catalogue\CategoryRepository : couche d'acces des entites CRUD (all/find/create/update/ setActive/nameExists/slugExists), testable via DatabaseInterface.
  • CategoryController (index/create/store/edit/update/toggle) : chaque action guard('category.manage') (RG-T03), mutations CSRF (RG-T01) + validation serveur (RG-T18 : requis/format/bornes/unicite, display_order 0..65535) + allowlist de colonnes (RG-T16). Pas de suppression dure (FK RESTRICT) : bascule is_active. Violation d'unicite concurrente traduite en 422. Flash apres redirection.
  • Vues admin/categories/{index,form} + admin/not_found. Revue : 6 findings corriges (borne display_order, violation unique -> 422, +4 tests de regression).

Set-PIN self-service (merge ; PR #16)

  • ProfileController -> GET/POST /admin/profile/pin : l'utilisateur connecte definit/change SON propre PIN (cible = guard.userId de session, pas un champ de form -> pas d'IDOR). CSRF + validation serveur (numerique + bornes via meetsLengthPolicy, confirmation). Hash argon2id. Ecriture gardee sur 1 ligne affectee (pas de faux succes). UserRepository : setPinHash/pinIsSet.
  • Decision PIN actee : modele identifiant equipier + PIN pour les actions sensibles (attribution individuelle). PinVerifier::resolveActingUser(email, pin) reste a ajouter en chunk Produits.
  • E2E : l'admin a un PIN dev = 4729 en base (pose via la page), ce qui debloque le gate Produits.
  • Revue : 3 findings corriges (fallback ?? 0 retire, gate ligne affectee, assertion cible = session).

Etat Git (post-chunks)

dev   f63ac98   (auth #11 + RBAC #12 + PIN #13 + shell #14 + categories #15 + set-PIN #16 ; == forgejo/dev)
152 tests (unit + integration DB auto-skippee), PHPStan L6 propre. Branches feature supprimees.
Hors-scope untracked : package*.json, SESSION_RESUME.md, journal P1.

Pattern CRUD admin (a reutiliser pour produits/menus/users)

  1. App\Catalogue\<Entite>Repository (DatabaseInterface) : requetes preparees, unicite.
  2. <Entite>Controller extends AdminController : par action -> guard(<permission>) -> (mutation : Csrf::validate) -> validation serveur + allowlist -> repo -> redirect + setFlash, ou re-rendu 422.
  3. Vues admin/<entite>/{index,form} rendues dans le shell ; tout texte echappe.
  4. Actions sensibles (RG-T13) -> PinVerifier + audit_log (RG-T14) dans la meme transaction.
  5. Pas de suppression dure si FK RESTRICT -> desactivation.
  6. Tests : controleur (double via hooks), repository (integration DB auto-skippee).

A faire a la reprise

  • CRUD Produits (chunk en cours) : cas riche (price_cents, vat_rate {55,100}, category_id FK, is_available, image, display_order). Premier usage reel de PinVerifier : PIN exige uniquement si prix/TVA change (8.2 RG-4) et a la suppression (8.3), modele identifiant equipier + PIN via PinVerifier::resolveActingUser(email, pin) (a ajouter) -> acting_user_id ecrit dans audit_log dans la meme transaction (RG-T14). Suppression dure seulement si non reference (FK RESTRICT depuis order_item / menu.burger_product_id) sinon 422. Reutilise les bornes d'entiers durcies (revue categories).
  • Ensuite : Menus (+ slots), Ingredients/stock, Users + matrice RBAC, Stats.
  • Differe : seed ingredients/recettes ; revoquer anciens PAT GitHub.

Session : 2026-06-15 (suite 2) — RBAC P2 (PR #12) + moteur PIN (PR #13), tous deux merges

Vue d'ensemble

Poursuite directe de la session auth. RBAC livre et merge (PR #12), puis moteur PIN d'action sensible construit (commit/PR en attente apres revue). Memes patterns que l'auth : services dependant de DatabaseInterface, controleurs non-final pour le seam de test, double FakeDatabase, tests unit + integration auto-skippee, revue adversariale par panel.

RBAC (merge ; dev = f979a23 ; PR #12)

  • Authorizer : can(role_id, code) / permissionsFor(role_id) / roleCode(role_id) ; verifie une PERMISSION (RG-T03), rechargee depuis la base a chaque appel (10.4 RG-3) ; un role is_active = 0 ne confere rien.
  • AuthenticatedController (dans App\Controllers, pas le Core, pour ne pas inverser la dependance) : cable SessionGuard (RG-6/RG-T02) + Authorizer.
  • MeController -> GET /api/me : 401 AUTH_REQUIRED si session absente/expiree/inactive, sinon identite + permissions. Premier consommateur reel du SessionGuard (enfin cable).
  • Revue : 3 findings corriges (roleCode ne filtrait pas is_active ; couverture du predicat is_active via FakeDatabase.roleActive + un test d'integration AuthorizerDbTest contre le vrai schema ; assertions de liaison par code de permission). 1 refute (le SessionGuard ne relit pas role_id en cours de session = by-design 10.4 RG-3 : la session stocke role_id, seules les permissions se rechargent).

PIN (merge ; PR #13)

  • PinVerifier : verify(user_id, pin) contre user.pin_hash (argon2id, default-deny, filtre is_active = 1) ; meetsLengthPolicy (chiffres ASCII, bornes min/max STAFF_PIN_MIN/MAX_LENGTH, RG-T18). Primitif RG-T13 reutilise par chaque operation sensible en P3.
  • 119 tests verts (unit + integration, dont la garde du filtre is_active contre le vrai schema), PHPStan L6 propre.
  • Revue : 3 findings corriges (decoy argon2id sur le chemin sans PIN pour egaliser le timing ; politique de longueur durcie ctype_digit + max ; couverture du filtre is_active). 2 refutes (throttle PIN = concern orchestrateur P3 ; cast (string) redondant inoffensif).
  • Perimetre P2 = le primitif seul. Les operations sensibles gardees (annulation, prix/TVA, suppressions, correction d'inventaire, gestion user/RBAC, effacement PII), la definition d'un PIN (set/change) et le cablage PIN + audit_log dans la meme transaction sont P3 (flux deja specifie dans docs/uml/security-sequence.md pour CANCEL_ORDER).

Etat Git

dev   7c35f8e   (auth PR #11 + RBAC PR #12 + PIN PR #13 ; == forgejo/dev ; push-mirror -> GitHub)
Branches feature supprimees (remote auto-merge + local). Working tree sur dev, propre.
Hors-scope untracked : package*.json, SESSION_RESUME.md, journal P1

A faire a la reprise

  • P3 CRUD admin : les pages admin deviennent des vues rendues serveur passant par AuthenticatedController. Chaque operation cable alors SessionGuard + Authorizer::can(permission)
    • PinVerifier (actions sensibles) + ecriture audit_log dans la meme transaction (RG-T08/RG-T14). C'est en P3 que SessionGuard / Authorizer / PinVerifier sont reellement appliques aux operations, et que les pages statiques (.html servies par Apache) deviennent protegeables.
  • Modele d'attribution PIN sur poste partage a trancher en P3 : PIN seul (identifie l'individu) vs identifiant equipier + PIN. Le primitif verify(user_id, pin) supporte les deux.
  • Differe : seed ingredients/recettes ; revoquer les anciens PAT GitHub.

Session : 2026-06-15 (suite) — P2 Auth back-office mergee (PR #11) + doc API + convention snake_case

Vue d'ensemble

Livraison de la couche authentification back-office (P2), conçue via un panel de design (3 architectes : testabilite / securite / simplicite) puis durcie par une revue adversariale (6 findings confirmes corriges). Mergee sur dev en auto-merge sur CI verte (PR #11, squash = 1b0b20c). En bonus : doc API et arbitrage de la convention de nommage.

Ce qui a ete fait

  • Prerequis compose : ARGON2_*, ACCOUNT_LOCKOUT_*, IP_THROTTLE_*, STAFF_PIN_MIN_LENGTH, PASSWORD_RESET_TTL passes au conteneur wakdo-app (deja dans .env.example).
  • Core etendu (additif) : Request::formBody() (POST urlencode) + Request::clientIp() (IP reelle = dernier hop X-Forwarded-For derriere Traefik, validee, repli REMOTE_ADDR) ; Database::transaction(callable): void (atomicite RG-T08) + DatabaseInterface (seam de test) ; accesseurs lecture Response (body/header/headers).
  • Domaine App\Auth : AuthService (12.1 login + 12.2 logout), PasswordResetService (12.3), SessionGuard (RG-6 + RG-T02 — ecrit et teste mais PAS encore cable : c'est le travail RBAC), ThrottlePolicy (backoff degressif), PasswordHasher (argon2id + leurre de timing en cache statique process), Csrf (synchroniseur + rotation), SessionManager (seul a toucher $_SESSION/cookie, mode test memoire), Mailer/LogMailer (lien reset journalise, pas de SMTP en P2), AuthResult/GuardResult.
  • Controllers + vues + routes : AuthController + PasswordResetController (non-final pour le seam de test), vues serveur auth/{login,forgot,reset}.php (CSRF cache, htmlspecialchars), 7 routes sur le vhost admin (/login, /logout, /forgot_password, /reset_password, ...).
  • Tests : 98 verts (unit sans DB + integration DB auto-skippee). PHPStan L6 propre.
  • Doc API : docs/api/conventions.md (conventions + listing des endpoints, en service + projete).

Decisions actees

  • Login = vue PHP rendue serveur (form POST + 302 vers role.default_route), pas une API JSON : le back-office est du MVC serveur.
  • Convention de nommage des URL = minuscule + snake_case (apres challenge utilisateur + fact-check : le minuscule est source RFC 3986, aucun standard n'impose - vs _, la coherence avec la DB et les champs JSON tranche pour _). Routes : /forgot_password, /reset_password ; /api/<ressource> au pluriel snake (/api/order_items). Les champs JSON suivent le dictionnaire (snake_case).
  • Bug attrape en E2E : PDO::ATTR_EMULATE_PREPARES = false interdit de lier un meme placeholder nomme plusieurs fois dans une requete -> placeholders distincts.
  • Corrections de revue : parite du profil d'ecritures sur email inconnu (UPDATE no-op sur id = 0, anti-enumeration) ; increment du compteur IP login_throttle rendu atomique cote SQL (anti lost-update) ; leurre argon2id mis en cache statique (parite de timing sans surcout par requete).

Boucle de verification locale (pas de PHP sur l'hote)

# unit + analyse (image PHP du projet, conteneur jetable) :
docker run --rm -v "$PWD":/app -w /app wakdo-wakdo-app php phpunit.phar -c phpunit.xml
docker run --rm -v "$PWD":/app -w /app wakdo-wakdo-app php -d memory_limit=-1 phpstan.phar analyse --no-progress --error-format=raw
# integration DB (auto-skip sans le flag) :
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

Les *.phar (phpunit 11.5.2 / phpstan 1.12.27) sont gitignores ; les telecharger si absents.

Etat Git (post-session)

dev   1b0b20c   (P2 auth merge, == forgejo/dev ; push-mirror -> GitHub auto)
feat/p2-auth : supprimee cote remote par l'auto-merge ; branche locale stale (supprimable)
Working tree : hors-scope habituels untracked (package*.json, SESSION_RESUME, journal P1)

A faire a la reprise — RBAC (demarre juste apres cette mise a jour)

  • Service d'autorisation : can(role_id, permission_code) via role_permission JOIN permission, recharge depuis la DB a chaque verification (mct/mlt 10.4 RG-3 ; la session ne stocke que role_id). Verifie une permission, pas un nom de role (RG-T03).
  • Cabler SessionGuard::check() en tete des routes protegees (idle/absolu/is_active), avec redirection vers /login si invalide. En P2 il n'y a pas encore de route protegee : on en cree une reelle pour brancher et tester la chaine (ex. / devient le landing authentifie, et/ou /api/me).
  • PIN actions sensibles (RG-T13) sur le sous-ensemble sensible : annulation, prix/TVA, RBAC, gestion utilisateur, correction d'inventaire (cf. docs/uml/security-sequence.md).
  • S'appuie sur le seed (5 roles + 23 permissions + matrice deja en base).

Session : 2026-06-15 (P1 conception finie + traduction FR + P2 demarre : DB + seed + Core)

Vue d'ensemble

Session marathon, trois phases :

  1. Pivot security-by-design boucle (A->G) : threat model, infra/config secu, CI/CD Forgejo Actions, diagrammes MCD + MLD. P1 conception terminee.
  2. Traduction FR de la prose des 5 docs Merise (identifiants/code inchanges), via 2 workflows. Convention projet : FR ASCII (sans accents).
  3. P2 demarre (le code !) : DDL 21 tables + runners migrations/seed, seed data, Core PHP from-scratch (squelette MVC, namespace App\ -> src/app/). Tout merge sur dev, identique Forgejo == GitHub.

P2 back squelette (en cours, deja merge sur dev)

  • DB foundation (PR #6) : db/migrations/0001_init_schema.sql (21 tables, verifie executable sur MariaDB reel), db/migrate.sh + db/seed.sh (idempotents), make migrate/make seed cables.
  • Seed (PR #8) : 5 roles + 23 permissions + matrice (manager = user.read lecture seule) + 14 allergenes INCO + 1 admin (argon2id, admin@wakdo.local / WakdoAdmin2026! dev) + catalogue (9 cat / 53 produits / 13 menus + composition). Differe : ingredients/recettes (couche stock, P3).
  • Core PHP (PR #9 + #10) : src/app/{Core,Controllers,Views} (App\ -> src/app), front controller src/public/admin/index.php. Autoloader PSR-4, Config getenv, Database PDO (prepared, lazy), Router, HealthController (GET /api/health -> DB reelle, categories:9). PHPUnit (.phar) + PHPStan L6, sans Composer.

Ce qui a ete fait (lots du pivot SbD)

  • A threat model STRIDE + classification 4 niveaux (PROJECT_CONTEXT SS19 + security-sequence.md).
  • B PROJECT_CONTEXT : drift GitHub->Forgejo Actions corrige, couche secu integree, planning rechiffre (P0 22 / P1 38 / P7 22 ; total 272h), decision #16 SbD.
  • C infra/config : .env.example (argon2id/lockout/throttle IP+compte/retention RGPD), php.ini durci (allow_url_*off, cgi.fix_pathinfo=0, IDs session, disable_functions RCE), .gitleaks.toml, scripts/forgejo-branch-protection.sh, doc runner. act_runner enregistre.
  • D SECURITY.md, checklist secu dans PR template, .forgejo/workflows/ci.yml (secret-scan gitleaks + php-lint + static-tests PHPStan/PHPUnit gardes jusqu'a P2), scripts/forgejo-pr-automerge.sh. Auto-merge teste et valide (PR #2, #3, #4).
  • E diagrammes MCD : 4 sous-domaines en Mermaid + SVG (mcd-{catalogue,ingredients-stock,order,rbac}), vieux .drawio v0.1 supprimes, mcd.md SS3/SS11 reecrites.
  • F PR #3 feat/p1-conception -> dev auto-mergee sur CI verte (squash), branche supprimee.
  • G push-mirror Forgejo->GitHub configure+teste (sync auto a chaque commit) ; historique git verifie sans secret (gitleaks + scan manuel). Reste cote user : revoquer anciens PAT GitHub (Session 6).
  • + diagrammes MLD : 4 sous-domaines relationnels (Mermaid+SVG, mld-*), PR #4 auto-mergee.

Etat Git (post-session) — tout aligne local == Forgejo == GitHub

main  5104040   (derniere release)
dev   c8f5370   (P1 conception FR + P2 : DB foundation + seed + Core skeleton src/app)
Code applicatif : src/app/{Core,Controllers,Views} (App\ -> src/app), front src/public/admin/index.php
Branches locales : dev, main (aucune feature en cours). Working tree : hors-scope BYAN + SESSION_RESUME (local)

Infra / forge / CI (a retenir)

  • git.acadenice.com = Thanos, PROD (serveur distinct 72.61.105.12). NE PAS confondre avec le forgejo local de stark git.stark.a3n.fr. Voir memoire project_forge_topology.
  • CI Forgejo Actions activee au niveau instance (FORGEJO__actions__ENABLED=true, fait par le user). Runner forgejo-runner-wakdo tourne sur stark, pointe la prod. Apres restart du forgejo prod -> docker restart forgejo-runner-wakdo (sinon boucle 404).
  • CI static-tests = SANS Composer : phpstan.phar + phpunit.phar epingles. Le runner (node:20-bookworm, PHP 8.2) installe php-xml php-mbstring (sinon PHPUnit manque dom/mbstring) — deja dans ci.yml.
  • Auto-merge OPT-IN par label auto-merge : le gate verifie le label EN SHELL via l'API (GET issues/PR/labels + grep), PAS via if: contains(labels...) de Forgejo (NON fiable : avait merge PR #9 sans label -> corrige PR #10). PR verte + label -> fusionne ; PR verte sans label -> reste ouverte.
  • Required checks (dev+main) : les 3 contextes precis CI / {secret-scan,php-lint,static-tests} (pull_request) (pas le glob CI / * qui incluait le job auto-merge skippe). Push-mirror -> GitHub auto.

En attente du user

  • Relecture des diagrammes MCD + MLD (4+4 sous-domaines) — le user lisait les docs a la pause. Si un layout ne plait pas, ajuster via une petite PR.
  • Decision : auto-merger directement ou faire valider les diagrammes avant merge la prochaine fois.

A faire a la reprise (P2 suite)

  • Auth : sessions PHP + argon2id (login), regeneration d'ID a la connexion, idle 4h / absolute 10h. Prerequis : passer les vars ARGON2_* / SESSION_* / lockout / throttle au conteneur wakdo-app (bloc environment: du docker-compose.yml) — PAS encore fait (seules DB_/APP_/SESSION_/CORS_ y sont).
  • RBAC : middleware de permissions (teste une permission, pas un nom de role), protection routes admin
    • PIN pour actions sensibles. S'appuie sur le seed (roles/permissions/matrice deja en base).
  • Seed ingredients/recettes (differe) : decisions de modelisation (quels ingredients, quantites) avec le user.
  • Hygiene : revoquer les anciens PAT GitHub (Session 6).

Reprendre

cd /home/acadenice/corentin_wakdo
git checkout dev && git fetch forgejo dev && git merge --ff-only forgejo/dev
git log --oneline -6 dev

Session 2026-06-12 (relecture security-by-design + modele stock en % + lot A threat model)

Note : ce doc avait derive (fige a Session 7, 2026-05-21). Entre-temps : v0.2 prod-like 19 entites + migration Forgejo (2026-06-04, voir docs/journal/2026-06-04--*.md) puis demarrage du pivot security-by-design (2026-06-11). Le bloc ci-dessous repart de l'etat reel.

Vue d'ensemble

Consolidation du pivot security-by-design sur feat/p1-conception. Trois temps :

  1. Relecture des 3 decisions securite (RGPD, oversell, brute-force) : les 3 directions validees. Le challenge a fait emerger une simplification (oversell) et un upgrade (stock %).
  2. Change-set applique aux 5 docs Merise via 1 workflow (5 editeurs paralleles + 4 critiques adversariaux), puis correctifs manuels des residus rates par les critiques.
  3. Lot A ecrit via 1 workflow (2 auteurs + 2 critiques) : threat model + classification dans PROJECT_CONTEXT §19, et docs/uml/security-sequence.md.

Decisions actees cette session

  • Stock en vrais % : ingredient porte stock_capacity (INT, CHECK > 0 = reference 100% + garde anti div/0), low_stock_pct (def 10), critical_stock_pct (def 5) ; stock_quantity signe (peut etre negatif). stock_pct = ROUND(stock_quantity/stock_capacity*100) calcule. 3 bandes : normal / alerte (le manager retire via is_available OU re-stocke) / auto-OOS sous le critique.
  • Disponibilite produit CALCULEE (RG-T21) : commandable ssi is_available=1 AND chaque ingredient non-retirable > critical. Pas de cascade ni flag ; retrait manuel = override dur.
  • login_throttle = table (entite 21) : throttle brute-force per-IP, en plus du compteur per-compte sur user.
  • Drop SELECT ... FOR UPDATE : decrement stock = UPDATE ... stock = stock - :units atomique (plus de read-gate, plus de risque deadlock). idempotency_key conserve.
  • Drift MCD §5.1 corrige : product_ingredient.quantity -> quantity_normal/quantity_maxi.

Etat Git (post-session)

Branche : feat/p1-conception
5 commits POSES cette session (non pushes - le push partira avec la PR) :
  fadf0bd  DICT - SbD data layer, 21 entities
  a1692b6  MCD  - SbD entities + % stock model, drift fix
  14348ba  MLD  - audit_log + login_throttle tables, % stock columns
  0f57a44  MCT  - SbD operations, PIN gating, computed availability
  5c34f6b  MLT  - RG-T13-T21, atomic decrement, throttle, RGPD

Working tree UNCOMMITTED (tenu volontairement) :
  docs/PROJECT_CONTEXT.md        (§19 threat model + classification ECRIT ; tenu car lot B
                                  va aussi toucher §7/§11)
  docs/uml/security-sequence.md  (NOUVEAU, lot A, fini, verifie)
  docs/uml/{sequence-passer-commande,state-commande,use-cases}.md  (drift-fix v0.2, pret,
                                  a grouper avec security-sequence.md)
  + journal 2026-06-04 untracked ; hors-scope BYAN (.claude, Makefile, docker-compose, package*)

A faire a la reprise (ordre)

  • B : PROJECT_CONTEXT §7/§11 (retirer « MVP », 21 entites, rechiffrer planning) -> puis commit PROJECT_CONTEXT (§19 + §7/§11) + les 4 docs UML.
  • C : infra/config secu (.env.example argon2/lockout/retention/seuils, php.ini durci, secret-scan, ruling branch-protection).
  • D : SDLC (SECURITY.md, checklist PR template, jobs CI Forgejo PHPStan/secret-scan).
  • E : regenerer les drawio MCD/MLD pour 21 entites (les .md sont en Mermaid inline).
  • F : clore -> PR feat/p1-conception -> dev (base = dev !), rafraichir ce doc.
  • G : roter le token Forgejo expose ; decider push-mirror Forgejo->GitHub.

Reprendre

cd /home/acadenice/corentin_wakdo
git branch --show-current        # feat/p1-conception
git log --oneline -6             # voir les 5 commits SbD
git status --short               # PROJECT_CONTEXT + UML uncommitted

Session precedente : 2026-05-21 (Session 7 - P1 conception : 5 docs Merise/UML + machine a etats commande unifiee)

Vue d'ensemble

Session centree sur la reprise de P1 conception. Trois resultats :

  1. Rapatriement P1 sur feat/p1-conception : les fichiers P1 (mcd.md + diagrammes) flottaient dans le working tree de la branche demo demo/p5-front-and-p3-admin. Portes proprement sur feat/p1-conception (stash des fichiers BYAN hors-scope, switch, pop). Les 4 .drawio y etaient deja commites (64f5a27), identiques au working tree.
  2. 5 docs P1 produits via 2 agents (expert-merise-agile + architect), puis normalises : MCT, MLT, use-cases, state-commande, sequence-passer-commande.
  3. Machine a etats de commande unifiee : resolution d'une contradiction qui preexistait entre dictionary.md, PROJECT_CONTEXT.md et le brief initial. Vocabulaire desormais coherent sur toute la doc.

Etat Git actuel (post-Session 7)

Repo : /home/acadenice/corentin_wakdo/
Branche courante : feat/p1-conception (rien commite cette session)

Working tree P1 (untracked, a commiter apres validation drawio) :
  docs/merise/mcd.md            (MCD, refs encore vers SVG Mermaid - cf. pivot drawio non termine)
  docs/merise/mct.md            (NEW - 24 operations metier)
  docs/merise/mlt.md            (NEW - preconditions/regles/postconditions)
  docs/uml/use-cases.md         (NEW)
  docs/uml/state-commande.md    (NEW)
  docs/uml/sequence-passer-commande.md (NEW)
  docs/merise/_diagrams/*.mmd + *.svg  (Mermaid leftover, a supprimer si on finit le pivot drawio)

Working tree modifie (tracked) :
  docs/PROJECT_CONTEXT.md       (ligne statut realignee sur machine canonique)

.drawio : commites sur feat/p1-conception (clean), en attente validation visuelle user sur le site drawio.

Hors-scope BYAN (persistants, jamais commites) :
  .claude/CLAUDE.md, .claude/rules/byan-agents.md, Makefile, package.json, package-lock.json

Decision majeure : machine a etats de commande (CANONIQUE)

Trois vocabulaires se contredisaient (ENUM dictionnaire avec paiement / PROJECT_CONTEXT sans paiement / noms FR introduits par erreur dans le brief Merise). Tranche par le user :

  • Deux phases : le client compose (pending_payment) PUIS paie (paid), apres quoi la commande passe en preparation. Le paiement EXISTE dans le cycle.
  • Termes en anglais (code-facing), valeurs ENUM du dictionnaire.
  • Machine retenue : pending_payment -> paid -> preparing -> ready -> delivered
  • cancelled atteignable depuis tout etat non remis (pending_payment, paid, preparing, ready) : annulable a tout moment tant que non livree (modification / annulation / remboursement client). delivered et cancelled finaux.

Applique partout : dictionary.md (deja correct), PROJECT_CONTEXT.md (corrige ligne 61), mct.md, mlt.md, state-commande.md, use-cases.md, sequence-passer-commande.md.

Autres decisions actees Session 7

Decision Contexte
Outil diagramme MCD = drawio User valide les 4 .drawio lui-meme sur le site (pas encore valides). Pivot Mermaid->drawio a finir cote pipeline + refs mcd.md
Pas de parcours employe dedie Les employes sont couverts par le diagramme de cas d'utilisation (use-cases) + diagramme d'etats. Ockham, evite le doublon
Production parallele en respectant les dependances On fait ce qui ne depend PAS du MCD (dependance nulle ou faible). On NE fait PAS ce qui en depend moyennement ou fortement (MLD, class-diagram) tant que les .drawio ne sont pas valides
MOT saute (rappel) Coherent Session 4 (raccourci agile MCT -> MLT direct)

Decisions secondaires EN SUSPENS (remontees par l'agent Merise, a trancher avant MLD)

  1. source (canal : kiosk/comptoir/drive) vs mode_consommation (fiscal : sur_place/a_emporter/drive) : deux dimensions distinctes. source est absent du dictionnaire et du MCD. A ajouter avant de generer le DDL.
  2. user_id sur commande : aucune tracabilite de l'equipier qui saisit / prend en charge / livre. A amender dans le MCD si stats par equipier souhaitees.

(Points mineurs documentes dans mct.md section 14 et mlt.md section 13 : service_day non materialise, etc.)

A faire lors de la reprise (ordre recommande)

  1. User valide les 4 .drawio sur le site drawio (preview Markdown ne rend pas Mermaid sans extension ; les .drawio/.svg s'affichent en revanche).
  2. Trancher les 2 decisions secondaires (source vs mode_consommation, user_id sur commande) - elles debloquent le MLD + class-diagram.
  3. Finir le pivot drawio (si confirme) : cible Makefile docs-render-drawio (image jgraph/drawio dispo localement), regenerer les SVG depuis les .drawio, reecrire les refs dans mcd.md (actuellement vers SVG Mermaid), supprimer les .mmd/.svg Mermaid.
  4. Produire MLD + class-diagram une fois le MCD valide et les decisions secondaires tranchees.
  5. Commiter le lot P1 conception (option : 1 commit par doc) sur feat/p1-conception, puis PR vers dev (vigilance : base = dev, pas main).

Commande exacte pour reprendre

cd /home/acadenice/corentin_wakdo
git status
git branch --show-current   # attendu : feat/p1-conception
ls docs/merise/             # mcd.md, mct.md, mlt.md, dictionary.md
ls docs/uml/                # use-cases.md, state-commande.md, sequence-passer-commande.md

Session precedente : 2026-05-09 (Session 6 - drawio + P5 front complet en remote control)

Vue d'ensemble

Session ~3-4h en remote control mobile qui a couvert 2 gros chantiers et un long detour sur l'automation des PRs :

  1. Pivot Mermaid -> drawio sur le MCD : 4 fichiers .drawio XML generes pour gain de controle layout (planarite du global non resoluble par mmdc)
  2. Front P5 complet anticipe : 2 runs d'agent UX (Sally) ont produit 7 pages HTML kiosk + 7 modules JS vanilla + JSON fallback statique. Flux complet welcome -> confirmation, live sur le vhost.
  3. Setup automation PR via API : detour sur fine-grained PATs (3 tentatives KO sur policy org AcadeNice "approval required"), resolu avec un classic PAT ghp_ en attendant l'approbation admin lundi.

2 PR ouvertes sur GitHub :

  • #4 ready : front P5 complet (7 commits)
  • #5 draft : 4 .drawio sources, en attente cleanup et suite Merise/UML

Etat Git actuel (post-Session 6)

Repo : /home/acadenice/corentin_wakdo/
Remote : git@github-wakdo:AcadeNice/wakdo_corentin.git

Branches :
  main                         00a3f82  (v0.1.0)
  dev                          68db2ee
  feat/p1-conception           64f5a27  (PR #5 draft : 4 .drawio committed)
  feat/p5-front-landing        6a7e772  (PR #4 ready : 7 commits P5 complet)  <- HEAD post-session
  feat/infra-docker            b09c461  (mergee, conservee)
  feat/p1-assets-import        24e733b  (mergee, conservee)
  feat/p1-stubs-and-dictionary d1a9876  (mergee, conservee)

Tags :
  v0.1.0                       00a3f82  Infrastructure foundation

Working tree out-of-scope (BYAN, persistent depuis sessions precedentes) :
  .claude/CLAUDE.md, .claude/rules/byan-agents.md, Makefile
  package.json, package-lock.json
  docs/SESSION_RESUME.md (ce fichier)

Working tree P1 (uncommitted, voyage entre branches lors des switches) :
  docs/merise/mcd.md
  docs/merise/_diagrams/*.mmd  (Mermaid leftover, a supprimer apres render drawio)
  docs/merise/_diagrams/*.svg  (Mermaid render, idem)

PRs ouvertes

# Titre Branche Base Statut
4 feat(front): P5 kiosk complete flow with vanilla JS and JSON fallback feat/p5-front-landing dev Ready for review
5 docs(merise): MCD diagrams in drawio XML (4 files) feat/p1-conception dev Draft

Decisions actees Session 6

Decision Contexte
Switch Mermaid -> drawio pour MCD Planarite du global non resoluble par mmdc auto-layout, controle manuel requis
4 .drawio separes (1 par diagramme) Plus simple a editer et diff que multi-page
Front P5 anticipe pendant P1 Data contract gele par brief ecole (JSON sources), front consomme JSON = consomme future API au mapping pres
Classic PAT (ghp_) au lieu de fine-grained AcadeNice Org AcadeNice policy "approval required", admin pas dispo le weekend
Branche front renommee p1 -> p5 Front borne = livrable P5 per plan SDLC (independant de la phase de realisation)
Auto-validation 7 checks par l'agent Remote control mobile = pas de validation visuelle facile, agent doit s'auto-verifier
Mode JSON fallback statique dans borne/data/ Apache bind-mount ne sert pas _sources/, copie statique = solution simple. Swap point unique dans data.js pour P4
TVA 10% (taux restauration FR 2024 simplifie) TODO P3 : valider avec comptable les variations sur place vs a emporter, alcool, etc.
gh dans Docker = mauvaise idee Stack Docker = runtime app, pas dev tooling. gh ou curl appartient a l'host.
Token GitHub stocke dans .env (gitignore) Standard, pas de leak en commits, lu via source .env au moment du curl

Ce qui a ete fait chronologiquement

Bloc 1 - Pivot Mermaid -> drawio + 4 sources XML

  1. Decision drawio uniquement, 4 fichiers separes, manual layout
  2. Generation des 4 fichiers .drawio XML avec entites + cardinalites Merise (min,max) a partir des sources Mermaid
  3. Commit 64f5a27 : docs(merise): add drawio XML sources for MCD diagrams

Bloc 2 - 1er agent UX (welcome + categories scaffold)

  1. Spawn agent UX-designer (Sally) en background avec scope 2 ecrans (welcome + categories), flag isolation: "worktree"
  2. L'agent a base sa branche sur feat/p1-conception au lieu de dev (le worktree n'a pas vraiment isole comme attendu)
  3. Rebase feat/p1-front-landing --onto dev 64f5a27 pour droper le commit drawio comme parent
  4. Renommage feat/p1-front-landing -> feat/p5-front-landing (front borne = livrable P5)

Bloc 3 - Setup automation PR (long detour sur les PATs)

  1. Push des 2 branches (SSH agent socket /tmp/ssh-Evc7jT0fk2rs/agent.2611024)
  2. Tentative gh CLI dans Docker -> mauvaise idee, abandonne
  3. Tentative fine-grained PAT #1 : Resource owner = Imugiii -> 404 sur wakdo_corentin (org repo invisible pour PAT a owner perso)
  4. Fine-grained PAT #2 : meme probleme (Resource owner encore = Imugiii)
  5. Fine-grained PAT #3 avec Resource owner = AcadeNice -> token en "Pending review" (org policy "approval required")
  6. Fallback classic PAT (ghp_) -> fonctionne des generation, scope repo, admin sur le repo
  7. PR #4 (front ready) + PR #5 (drawio draft) creees via POST /repos/AcadeNice/wakdo_corentin/pulls

Bloc 4 - 2e agent UX (P5 complet)

  1. Spawn agent UX en background sur feat/p5-front-landing avec scope etendu : 5 nouvelles pages + JS state + JSON fallback
  2. Auto-validation 7 checks dans le brief (assets exist, links resolve, JSON valid, HTML closed, JS syntax, http server e2e, JSON fetch)
  3. Livrable : 5 pages HTML, 7 modules JS, 2 JSON normalises copies dans borne/data/, CSS etendu de 438 -> 1257 lignes
  4. 6 commits thematiques (6f5daca -> 6a7e772), 7/7 auto-checks PASS
  5. Push, mise a jour PR #4 (titre + body) via PATCH /repos/.../pulls/4
  6. Test live kiosk : les endpoints repondent 200 (welcome, categories, products, product, cart, payment, confirmation, JSON, CSS, JS, images)

Commande exacte pour reprendre

cd /home/acadenice/corentin_wakdo
git status
git branch --show-current
# Si HEAD = feat/p5-front-landing : tu peux tester le front sur https://corentin-wakdo.stark.a3n.fr/
# Pour reprendre P1 :
git checkout feat/p1-conception

A faire lors de la reprise (ordre recommande)

  1. Review visuelle PR #4 : tester le flux kiosk complet sur https://corentin-wakdo.stark.a3n.fr/, valider, merger dans dev (via web ou via API)
  2. Drawio render automatique : ajouter cible Makefile make docs-render-drawio qui utilise le container rlespinasse/drawio-export pour generer les SVG depuis les .drawio XML. Evite l'export manuel sur drawio web (galere sur mobile).
  3. Continuer P1 conception sur feat/p1-conception :
    • docs/merise/mct.md
    • docs/merise/mlt.md
    • docs/merise/mld.md
    • docs/uml/class-diagram.md
    • docs/uml/use-cases.md
    • docs/uml/state-commande.md
    • docs/uml/sequence-passer-commande.md
  4. Commit final mcd.md : une fois les SVG drawio generes, commit mcd.md + suppression des .mmd/anciens .svg Mermaid + Makefile mis a jour (drop docs-render mmdc, garder uniquement docs-render-drawio)
  5. Passage PR #5 draft -> ready (via PATCH API) quand tout le P1 conception est dedans
  6. Hygiene secu PATs : revoquer dans GitHub Settings :
    • 3 fine-grained github_pat_... (suffixes BE4y, UiZc, ljeC)
    • classic ghp_Rr5EkM4... (a rotater quand fine-grained AcadeNice approuve par admin lundi)

Note technique - isolation worktree

Le flag isolation: "worktree" sur l'Agent tool n'a pas cree de vrai worktree isole - les agents ont travaille directement sur le main repo (git worktree list ne montre qu'une entree). Pas grave en pratique mais a savoir pour les prochains spawns : instruire explicitement l'agent de ne pas switch de branche dans le main repo, ou de bosser en branche dediee pre-checked-out.


Session precedente : 2026-04-30 soir (Session 5 - notes perso + demarrage P1 conception + setup pipeline diagrammes)

Vue d'ensemble

Session moyenne (~3h) qui a couvert :

  1. Cloture P1 dictionnaire : commit + push + PR #3 mergee dans dev
  2. 4 notes perso ecrites (gitignore) : apache-fastcgi-pitfalls, docker-network-pools-rfc1918, enum-vs-table-reference, merise-yagni-quantite + index README mis a jour
  3. Demarrage P1 conception sur nouvelle branche feat/p1-conception (renommee depuis feat/p1-merise-conception pour inclure UML)
  4. MCD redige (docs/merise/mcd.md) avec 3 sous-domaines (Catalogue/Commande/RBAC) en Mermaid + tableau recap cardinalites Merise
  5. Pipeline mmdc setup : .mmd sources + SVG generes + make docs-render target
  6. Blocage layout MCD global : 10 entites + 10 associations = probleme planarite intrinseque, decision laissee en suspens

Aucun commit fait sur la branche feat/p1-conception — tout reste dans le working tree pour reprise propre.

Etat Git actuel (post-Session 5)

Repo : /home/acadenice/corentin_wakdo/
Remote : git@github-wakdo:AcadeNice/wakdo_corentin.git

Branches :
  main                          00a3f82  (v0.1.0)
  dev                           68db2ee  (= main + PR#1 + PR#2 + PR#3 mergees)
  feat/infra-docker             b09c461  (mergee, conservee)
  feat/p1-assets-import         24e733b  (mergee, conservee)
  feat/p1-stubs-and-dictionary  d1a9876  (mergee via PR#3, conservee)
  feat/p1-conception            68db2ee  (NOUVELLE, ZERO COMMIT, working tree only)

Tags :
  v0.1.0                        00a3f82  Infrastructure foundation

Working tree sur feat/p1-conception (a commit a la prochaine session) :
  docs/merise/mcd.md                       (NEW - 411 lignes)
  docs/merise/_diagrams/mcd-global.mmd     (NEW)
  docs/merise/_diagrams/mcd-global.svg     (NEW)
  docs/merise/_diagrams/mcd-catalogue.mmd  (NEW)
  docs/merise/_diagrams/mcd-catalogue.svg  (NEW)
  docs/merise/_diagrams/mcd-commande.mmd   (NEW)
  docs/merise/_diagrams/mcd-commande.svg   (NEW)
  docs/merise/_diagrams/mcd-rbac.mmd       (NEW)
  docs/merise/_diagrams/mcd-rbac.svg       (NEW)
  Makefile                                 (modified - target docs-render ajoute)
  docs/notes/README.md                     (modified, gitignore - 7 entries ajoutees)
  docs/notes/apache-fastcgi-pitfalls.md    (NEW, gitignore)
  docs/notes/docker-network-pools-rfc1918.md (NEW, gitignore)
  docs/notes/enum-vs-table-reference.md    (NEW, gitignore)
  docs/notes/merise-yagni-quantite.md      (NEW, gitignore)

Working tree out-of-scope (BYAN, deja modifies en sessions precedentes) :
  .claude/CLAUDE.md
  .claude/rules/byan-agents.md
  package.json, package-lock.json
  docs/SESSION_RESUME.md

Decisions actees Session 5

Decision Contexte
Branche renommee feat/p1-conception (au lieu de feat/p1-merise-conception) Pour inclure UML dans le scope de la PR
UML ajoute au scope P1 conception RNCP 37805 attend Merise + UML, pas que Merise
Granularite commits PR : option α (1 commit par doc) Coherent avec l'historique, squashable en fin de PR si besoin
Pipeline diagrammes : option B (mmdc local + SVG embed) Rendu portable Cursor/GitHub/PDF/Notion, regenerable via make docs-render
Ecriture des 4 notes perso AVANT le travail Merise Sujets frais dans le contexte (Session 4 + dictionnaire)
Auteur des notes = "BYAN" Coherent avec section 17 PROJECT_CONTEXT (transparence methodologie)
4 hedgings appliques (toujours/forcement -> tend a/implique) Hook PreToolUse fact-check intransigeant

Decision EN SUSPENS (a trancher en premier la prochaine session)

Layout du diagramme global MCD : avec 10 entites et 10 associations (dont 2 polymorphiques sur LIGNE_COMMANDE -> PRODUIT et MENU), il y a un probleme de planarite : impossible de placer toutes les entites sans croiser au moins 2 lignes. Mermaid auto-layout galere, Excalidraw manuel n'aide pas vraiment.

3 options en attente d'arbitrage :

  • A. Drop le global — supprimer section 3 du MCD, garder section 6 (tableau recap des cardinalites) + section 4 (3 sous-domaines Mermaid propres). Coherent avec l'approche Merise (decomposer si > 5 entites). Defendable au jury : "j'ai decompose, tableau recap = vue integree".
  • B. Excalidraw manuel — refaire le global a la main dans Excalidraw, export .excalidraw.svg (avec scene embedee), embed dans le MCD. Coute 20-30 min de layout manuel, perd la regen automatique.
  • C. Garder Mermaid en l'etat — assumer que le layout est croise mais jouer le compromis "decomposition prime sur visuel global".

Le user a dit "le choix n'est pas encore fait" (Session 5 fin de soiree, fatigue sur le sujet). A reprendre tete reposee.

Ce qui a ete fait chronologiquement

Bloc 1 - Cloture dictionnaire (commit + PR)

  1. Verification etat initial : branche feat/p1-stubs-and-dictionary avec b8f7d35 (stubs+fixes) commit, docs/merise/dictionary.md uncommitted
  2. Commit d1a9876 : docs(merise): data dictionary v0.1 - 10 entities + Mermaid ER diagram + 7 modeling notes
  3. Push branche, PR #3 ouverte manuellement (gh CLI absent), mergee sur dev
  4. git fetch + checkout dev + merge --ff-only origin/dev : sync OK sur 68db2ee

Bloc 2 - 4 notes perso (gitignore)

  1. Bascule sur Read au lieu de grep/sed apres blocage du hook tool-failure-guard sur "internal error" string presente dans vhost.conf (pattern legitime du commentaire, faux positif Bash output)
  2. apache-fastcgi-pitfalls.md (405 lignes) - 3 pieges Session 4 (DirectoryIndex, allowed_clients, R=200) + Q&A jury
  3. docker-network-pools-rfc1918.md (376 lignes) - saturation pools Docker sur stark, choix 192.168.148.0/24, RFC 1918, Q&A jury
  4. enum-vs-table-reference.md (381 lignes) - matrice de decision ENUM vs table, application aux 4 ENUMs Wakdo, Q&A jury
  5. merise-yagni-quantite.md (337 lignes) - YAGNI applique a menu_produit, audit source ecole 13 menus mono-portion, Q&A jury
  6. docs/notes/README.md index mis a jour : 7 nouvelles entrees (3 Session 4 deja redigees + 4 nouvelles)

Bloc 3 - Setup branche conception + cadrage

  1. Branche feat/p1-merise-conception creee depuis dev, puis renommee en feat/p1-conception apres discussion sur l'ajout UML au scope
  2. Decision : 8 documents prevus pour la PR :
    • Merise : MCD, MCT, MLT, MLD (4 docs dans docs/merise/)
    • UML : classes, use cases, etats, sequence (4 docs dans docs/uml/)
  3. docs/uml/ cree

Bloc 4 - MCD redige + setup pipeline diagrammes

  1. Premier draft MCD avec 4 diagrammes ASCII art (global + 3 sous-domaines)
    • tableau recap cardinalites Merise (0,N)/(1,1)
  2. User trouve l'ASCII moche -> bascule sur Mermaid erDiagram inline
  3. User ne voit pas le rendu Mermaid dans Cursor (pas d'extension installee) -> bascule sur SVG via mmdc
  4. Setup docs/merise/_diagrams/ : 4 fichiers .mmd extraits + 4 SVG generes via npx mmdc
  5. MCD edite : 4 blocs Mermaid remplaces par <img src="_diagrams/*.svg">
  6. Makefile : target docs-render ajoute, scanne tous les docs/**/_diagrams/*.mmd du projet, regen SVG (testee, OK 4/4)
  7. User constate que le global a des lignes croisees, tente Excalidraw, n'arrive pas a un layout logique -> decision laissee en suspens

Commande exacte pour reprendre

cd /home/acadenice/corentin_wakdo
git status                              # confirmer working tree intact
git branch --show-current               # doit etre feat/p1-conception
git log --oneline dev..HEAD             # doit etre vide (zero commit sur la branche)
ls docs/merise/                         # mcd.md + _diagrams/ presents
ls docs/notes/                          # 4 notes Session 5 + README maj

A faire lors de la reprise (ordre recommande)

  1. Trancher le layout MCD global (option A / B / C ci-dessus). Si A, editer mcd.md pour supprimer section 3, decrementer les numeros, et supprimer _diagrams/mcd-global.{mmd,svg}. Si B, faire le travail Excalidraw manuel. Si C, ne rien faire et continuer.

  2. Commit le MCD (option α : 1 commit par doc) :

    git add docs/merise/mcd.md docs/merise/_diagrams/ Makefile
    git commit -m "docs(merise): MCD v0.1 + pipeline mmdc -> SVG via make docs-render"
    
  3. Continuer P1 conception, dans l'ordre :

    • docs/merise/mct.md - operations metier + acteurs + flux
    • docs/merise/mlt.md - workflow logique (preconditions / regles / postconditions)
    • docs/merise/mld.md - schema relationnel formel
    • docs/uml/class-diagram.md - vue OOP (prepare PHP P2)
    • docs/uml/use-cases.md - acteurs + goals (kiosk client, manager, ...)
    • docs/uml/state-commande.md - machine a etats commande.statut
    • docs/uml/sequence-passer-commande.md - flux passer commande
  4. Push + PR vers dev quand les 7 docs restants sont commit. Vigilance : verifier base = dev (pas main !).

  5. Apres merge : continuer P1 implementation (DDL + seed + fallback) sur une branche feat/p1-implementation separee.


Session precedente : 2026-04-30 jour (Session 4 etendue - smoke test infra + import assets + P1 demarre)

Vue d'ensemble

Session tres longue (~6h cumulees) qui a couvert 3 grandes phases en une seule journee :

  1. Smoke test infra Docker sur le serveur stark : make init valide bout en bout, 4 services healthy, certs Let's Encrypt provisionnes
  2. Import assets ecole : 71 images normalisees + 2 JSON sources + maquette Figma PDF
  3. Demarrage P1 Merise : stubs unblock-403 + dictionnaire de donnees v0.1 (10 entites)

3 PR ont ete fusionnees (1 incident main->dev recupere) et 1 PR reste ouverte (la branche de la 3e phase n'est pas encore push).

Etat Git actuel (post-Session 4)

Repo : /home/acadenice/corentin_wakdo/
Remote : git@github-wakdo:AcadeNice/wakdo_corentin.git

Branches :
  main                         00a3f82  (v0.1.0 - infra foundation)
  dev                          84d2559  (= main + PR#2 assets)
  feat/infra-docker            b09c461  (mergee dans main via PR#1, conservee)
  feat/p1-assets-import        24e733b  (mergee dans dev via PR#2, conservee)
  feat/p1-stubs-and-dictionary b8f7d35  (LOCAL UNIQUEMENT - NON PUSHEE)
                                        + dictionnaire UNCOMMITTED dans le working tree

Tags :
  v0.1.0                       00a3f82  Infrastructure foundation (annotated, pushe)

Working tree out-of-scope (volontairement non commit) :
  .claude/CLAUDE.md, .claude/rules/* (modifies hors-projet, BYAN)
  package.json, package-lock.json (BYAN)
  docs/SESSION_RESUME.md (ce fichier - local perso)

Vue chronologique des PR

00a3f82 (main, dev, v0.1.0) Merge PR #1 from feat/infra-docker
  - INCIDENT : PR ouverte par defaut sur 'main' au lieu de 'dev'
  - REMEDIATION : git checkout dev && git merge --ff-only origin/main && git push origin dev
  - LECON : verifier le selecteur 'base branch' sur GitHub avant 'Create pull request'
  - 9 commits infra : compose, dockerfiles, smoke test fixes, FQDN switch, journal session 4

84d2559 (dev) Merge PR #2 from feat/p1-assets-import
  - PR sur la bonne base 'dev' cette fois
  - 1 commit : import des 2 JSON sources + 71 images normalisees + maquette PDF

Ce qui a ete fait (chronologique session)

Phase 1 - smoke test infra (avant pause)

  1. Conflit .env BYAN/Wakdo traite par fusion en 1 fichier (gitignore)
  2. Switch FQDN acadenice.fr -> stark.a3n.fr (zone wildcard existante, evite la provisioning DNS prerequise par le challenge HTTP-01 de Traefik)
  3. Smoke make init casse 3 fois et corrige :
    • Subnet explicite 192.168.148.0/24 (pools Docker satures)
    • init: true sur cron (dcron PID 1 setpgid)
    • Healthz statique dans /usr/local/apache2/htdocs/ (RewriteRule R=200 declenchait ErrorDocument template)
  4. Validation HTTPS externe : 4 services healthy, certs OK, /healthz isole
  5. Journal session ecrit (docs/journal/2026-04-30--smoke-test-infra.md)
  6. PR #1 -> incident main au lieu de dev -> remediation FF dev=main
  7. Tag v0.1.0 annote sur le merge commit
  8. Memoire feedback_no_absolutes.md enregistree (hook fact-check sensible)

Phase 2 - import assets ecole

  1. Drop zone docs/_inbox/ recue (9 Mo, 71 images + 2 JSON + 1 PDF + 1 readme)
  2. Diagnostic : naming "wacdo" vs notre "Wakdo", casse incoherente, 7 typos dans JSON
  3. Rangement final :
    • docs/merise/_sources/ (2 JSON + source-school.md provenance)
    • docs/design/ (maquette PDF + README pointant Figma)
    • src/public/borne/assets/images/ (71 images normalisees kebab-case lowercase)
  4. Workaround chown via container ephemere (src/ etait owned root par Docker bind-mount)
  5. PR #2 -> dev (workflow correct cette fois)

Phase 3 - demarrage P1 Merise

  1. Decisions cadrage P1 actees :
    • MOT skippe (raccourci agile MCT -> MLT direct)
    • Composition flexible (menu_produit avec role et position)
    • Pas de quantite sur menu_produit (YAGNI - 13 menus mono-portion)
    • 9 entites + 1 jointure RBAC : Categorie, Produit, Menu, MenuProduit, Commande, LigneCommande, User, Role, Permission, RolePermission
    • Pas de stock numerique (juste est_disponible boolean)
    • Pas de stats agregees (live queries)
    • Pas d'allergenes/nutrition pour MVP
  2. Stubs minimaux pour debloquer le 403 :
    • src/public/borne/index.html (HTML statique avec logo, vhost kiosk)
    • src/public/admin/index.php (PHP qui prouve la chaine FastCGI E2E)
  3. 2 bugs infra exposes par les stubs et fixes :
    • Apache DirectoryIndex ne contenait pas index.php (admin renvoyait 403)
    • PHP-FPM listen.allowed_clients = any rejete par PHP 8.3 (toutes les connexions Apache->PHP-FPM rejetees, FastCGI cassait silencieusement)
  4. Validation HTTPS externe : kiosk -> 200 HTML, admin -> 200 PHP rendu (PHP_VERSION et timestamp dynamique substitues)
  5. Commit b8f7d35 : feat(stubs): unblock 403 with kiosk and admin index pages, plus FastCGI fixes
  6. Dictionnaire de donnees v0.1 redige (docs/merise/dictionary.md) :
    • ~340 lignes, 10 entites detaillees
    • Diagramme entites-relations en Mermaid (rendu GitHub natif)
    • 7 notes de modelisation (FLOAT vs cents, ENUM vs table, STI, polymorphisme, audit fields, RFC 5321 emails, etc.)
    • Cross-validation avec PROJECT_CONTEXT.md et source ecole
  7. 3 notes techniques perso (docs/notes/, gitignore) :
    • rbac-roles-permissions.md : pattern RBAC dynamique vs statique, UI matrice, Q&A jury
    • monetary-int-cents.md : INT centimes + TVA pour mille, Goldberg ACM 1991, Stripe convention, 5 pieges
    • polymorphic-fk-snapshots.md : 2 colonnes nullables + discriminator + snapshots, Karwin SQL Antipatterns, integrite historique commandes
  8. Memoire feedback_notes_author.md mise a jour : auteur des notes = "BYAN" (pas un nom de LLM specifique), coherent avec la transparence projet section 17 PC

En cours (a reprendre)

Branche locale feat/p1-stubs-and-dictionary avec 1 commit fait + dictionnaire UNCOMMITTED.

Commande exacte pour reprendre

cd /home/acadenice/corentin_wakdo
git status                              # confirmer ?? docs/merise/dictionary.md
git branch --show-current               # doit etre feat/p1-stubs-and-dictionary
git log --oneline dev..HEAD             # voir b8f7d35 (stubs+fixes)

A faire lors de la reprise

  1. Commit le dictionnaire :

    git add docs/merise/dictionary.md
    git commit -m "docs(merise): data dictionary v0.1 - 10 entities + Mermaid ER diagram + 7 modeling notes
    
    Bottom-up derivation from school JSON sources + PROJECT_CONTEXT business rules.
    Covers : Categorie, Produit, Menu, MenuProduit, Commande, LigneCommande,
    User, Role, Permission, RolePermission. Decisions documented :
    prices in INT cents, VAT in per-mille, polymorphic FK with snapshots
    on ligne_commande, dynamic roles vs static permissions for RBAC."
    
  2. Push + PR :

    SSH_AUTH_SOCK=/tmp/ssh-Evc7jT0fk2rs/agent.2611024 git push -u origin feat/p1-stubs-and-dictionary
    

    Puis ouvrir PR via : https://github.com/AcadeNice/wakdo_corentin/compare/dev...feat/p1-stubs-and-dictionary?expand=1 VIGILANCE : verifier base = dev (pas main !) avant de cliquer Create.

  3. Continuer P1 sur une nouvelle branche feat/p1-merise-models (apres merge de la precedente) ou sur la meme branche etendue. Suite des etapes :

    • MCD : docs/merise/mcd.md avec un diagramme Mermaid plus formel (entites + associations + cardinalites min/max), distinct du diagramme preview du dictionnaire
    • MCT : docs/merise/mct.md - les operations metier (valider commande, encaisser paiement, marquer pret, ...)
    • MLT : docs/merise/mlt.md - workflow logique de chaque traitement (preconditions, regles, postconditions, sorties)
    • MLD : docs/merise/mld.md - schema relationnel formel
    • DDL : db/migrations/0001_init_schema.sql - SQL CREATE TABLE concret
    • Seed : db/seeds/0001_demo_data.sql - INSERT des 9 categories + 53 produits + 13 menus a partir des JSON sources, avec normalisation des prix en centimes
    • Export fallback JSON : scripts/export-fallback.{sh|php} qui genere src/public/borne/data/*.json depuis le seed (pour mode "Bloc 1 isole")
  4. Notes perso restantes a rediger (basse priorite, peut s'etaler sur plusieurs sessions) :

    • enum-vs-table-reference.md : quand utiliser ENUM vs table referentielle
    • docker-network-pools-rfc1918.md : pool saturation Docker, choix subnet explicite
    • apache-fastcgi-pitfalls.md : les 3 bugs infra de cette session (DirectoryIndex, listen.allowed_clients, RewriteRule R=200)
    • merise-yagni-quantite.md : application concrete de YAGNI sur menu_produit
  5. Optionnels post-merge (peuvent aller sur une branche feat/infra-polish separee apres P1) :

    • Investiguer redirect HTTP->HTTPS qui retourne 404 (interaction avec middleware global du Traefik d'hote)
    • Unifier le style init Docker (wakdo-app a tini explicite, wakdo-cron a init: true - incoherence stylistique a accepter ou unifier)

Workflow git en vigueur

  • Convention : feat/* -> dev (squash merge), dev -> main (avec tag vX.Y.Z annote)
  • Vigilance PR : verifier explicitement base branch = dev (le defaut GitHub est main)
  • Branches mergees : conservees comme trace historique
  • Procedure d'archive si une branche est abandonnee non-mergee :
    git tag -a archive/feat-xxx <branch-tip-sha> -m "abandoned: <reason>"
    git push origin archive/feat-xxx
    git push origin --delete feat-xxx
    git branch -D feat-xxx
    
  • Tags previsionnels : v0.1.0 (infra), v0.2.0 (P2 stubs+auth+CRUD basic), v0.3.0 (CRUD admin complet), ..., v1.0.0 (livrable jury)

Decisions structurelles actees Session 4

Decision Pourquoi
Fusion .env BYAN+Wakdo Outil tiers lit .env du cwd, separation .env.wakdo plus risquee
FQDN sur *.stark.a3n.fr Wildcard DNS existant, evite provisioning prerequis HTTP-01
Subnet explicite 192.168.148.0/24 (RFC 1918) Pools Docker satures sur hote partage
init: true sur cron dcron en PID 1 sans init reaper boucle sur setpgid Operation not permitted
Healthz statique htdocs RewriteRule R=200 declenche template ErrorDocument
APP_ENV=dev + APP_DEBUG=true Phase de construction, flip vers prod avant demo jury
Naming "wacdo" (source) vs "Wakdo" (projet) wacdo preserve dans _sources/ pour tracabilite ecole
Casse images normalisee kebab-case lowercase Anti-piege case-sensitive Linux dans Docker
MOT (modele organisationnel des traitements) skippe Raccourci agile MCT -> MLT direct
Composition flexible menu_produit (role+position) Defendable evolution future sans refacto
Pas de quantite sur menu_produit YAGNI - 13 menus mono-portion
Prix en INT centimes + TVA en pour mille Anti-FLOAT IEEE 754 (Goldberg ACM 1991)
Snapshots libelle+prix sur ligne_commande Integrite historique audit
Polymorphisme ligne_commande -> produit OR menu 2 cols nullable + discriminator + 2 FKs reelles
RBAC : roles+role-permission dynamiques, permissions statiques Permissions liees au code (declarees en migration)
Pas de stock numerique en MVP Juste est_disponible boolean
Pas de stats agregees Live queries SUM/GROUP BY suffisent
Pas d'allergenes/nutrition Hors source ecole, hors scope MVP
ENUM pour valeurs metier stables mode_consommation, statut, role -> 3-7 valeurs, ALTER si extension
Auteur notes perso = "BYAN" Coherent avec section 17 PC (transparence methodologie)

Prochaines etapes (apres merge feat/p1-stubs-and-dictionary -> dev)

P1 Conception Merise (semaines 2-3) - EN COURS
   1. Dictionnaire de donnees     v0.1 ECRIT (a commit)
   2. MCD                         a faire
   3. MCT                         a faire
   4. (MOT skippe)
   5. MLD                         a faire
   6. MLT                         a faire
   7. DDL                         a faire
   8. Seed data                   a faire
   9. JSON fallback               a faire

P2 Back squelette (semaines 4-6)
   - Core (Router, Autoloader, DB)
   - Auth (sessions PHP fichier + argon2id)
   - RBAC (Authorization service)
   - Front controller `index.php`

P3 CRUD admin (semaines 7-10)
   - CRUD produits, menus, categories
   - UI roles + assignment matrice permissions
   - CRUD users

P4 API REST (semaines 11-12)
   - Endpoints /api/categories, /api/menus, /api/produits, /api/orders
   - CORS + tests

P5 Front borne (semaines 13-16)
   - Integration maquette + Ajax + a11y RGAA
   - Mode JSON-seuls (fallback) + mode API-connecte

P6 Tests + finition (semaines 17-18)

P7 DevOps final (semaine 19) - GitHub Actions, crons, docs

P8 Prep soutenance (semaine 20)

Fichiers cles a consulter a la reprise

Fichier Contenu
docs/PROJECT_CONTEXT.md Source de verite projet (FQDN sur stark.a3n.fr, section 17 transparence IA)
docs/_ref/rncp-37805-referentiel.pdf Referentiel RNCP officiel
docs/_ref/rncp-37805-index.md Index texte compact des criteres (cherchable)
docs/journal/README.md Template + index des retros (3 entrees)
docs/journal/2026-04-30--smoke-test-infra.md Retro Session 4 phase 1 (smoke test)
docs/merise/dictionary.md Dictionnaire P1 v0.1 ECRIT (a commit)
docs/merise/_sources/ JSON sources ecole + provenance
docs/design/ Maquette PDF + lien Figma
docs/notes/ Notes perso revision oral (3 ecrites cette session, gitignore)
docs/SESSION_RESUME.md Ce fichier - a mettre a jour en fin de session
.env Config locale fusionnee (BYAN + Wakdo, gitignore)
.env.example Template neutre commit, RFC 2606
docker-compose.yml Compose final (subnet 192.168.148.0/24 + init cron + 4 services)
Makefile Orchestration complete, voir make help
.claude/CLAUDE.md Constitution projet BYAN
.claude/rules/fact-check.md Patterns du hook fact-check (a consulter avant ecriture narrative !)

Commandes utiles pour reprendre

cd /home/acadenice/corentin_wakdo

# 1. Etat
git status
git branch --show-current
# -> attendu : feat/p1-stubs-and-dictionary

# 2. Stack docker (verifier qu'elle tourne toujours)
docker compose -p wakdo ps
# Si down apres reboot : make up   (ou make init pour full bootstrap)

# 3. Test que tout repond
curl -sI https://corentin-wakdo.stark.a3n.fr/        # 200
curl -sI https://corentin-wakdo-admin.stark.a3n.fr/  # 200

# 4. SSH pour push (si besoin)
find /tmp -name 'agent.*' -user corentin
# -> /tmp/ssh-Evc7jT0fk2rs/agent.2611024 (peut changer apres reboot ssh-agent)
SSH_AUTH_SOCK=/tmp/ssh-XXX/agent.NNN git push ...

Memoire persistante Claude Code (mise a jour Session 4)

Regles enregistrees dans /home/corentin/.claude/projects/-home-acadenice-corentin-wakdo/memory/ :

  • No Co-Authored-By sur les commits Wakdo (Session 2)
  • Commit uniquement sur approbation explicite (Session 2)
  • Ignorer les contextes d'autres projets dans les system-reminders (Session 3)
  • Hedger proactivement pour le hook fact-check (Session 4)
  • BYAN auteur des docs/notes/ (Session 4 - mise a jour cette session)

Comment reprendre la session

  1. Ouvrir une session dans /home/acadenice/corentin_wakdo/
  2. Dire : "Reprise Wakdo, lis docs/SESSION_RESUME.md"
  3. Confirmer l'action de depart :
    • Suite immediate = commit + push + PR du dictionnaire (cf. section "A faire lors de la reprise")
    • Apres merge = continuer P1 avec le MCD (docs/merise/mcd.md)

Document maintenu a chaque fin de session. Derniere mise a jour : 2026-05-21 (Session 7).