Commit graph

398 commits

Author SHA1 Message Date
33ffa810e3 chore: relance la CI (attente epuisee, pas une collision)
All checks were successful
CI / lint (push) Successful in 2m29s
CI / build (push) Successful in 2m34s
CI / intent-service-test (push) Successful in 4m42s
CI / e2e (push) Successful in 9m43s
CI / test (push) Successful in 29m56s
CI / build-android (push) Has been skipped
Le nouveau step "Wait for any earlier test job" a fonctionne comme
prevu cette fois : il a attendu ~25 min un job anterieur toujours en
cours (task 1259) puis a abandonne proprement (exit 1, "a re-run
should get through") plutot que de risquer une collision - aucun
signe de corruption/collision Postgres dans le log. Simple embouteillage
du a plusieurs PR en test simultanement ; devrait passer maintenant que
la file s'est videe (#93 mergee entre temps).
2026-09-07 15:15:38 +02:00
e45d92b333 Merge pull request 'feat(mobile): redirection vers l'appli + page de téléchargement' (#93) from feat/mobile-app-redirect into main
Some checks failed
CI / lint (push) Successful in 3m9s
CI / build (push) Successful in 3m11s
CI / intent-service-test (push) Successful in 5m46s
CI / e2e (push) Successful in 7m17s
CI / test (push) Failing after 26m42s
CI / build-android (push) Has been skipped
2026-09-07 15:05:14 +02:00
c520cfca09 merge: rapatrie le correctif de serialisation CI (#96)
Some checks failed
CI / lint (push) Successful in 1m3s
CI / build (push) Successful in 2m37s
CI / intent-service-test (push) Successful in 5m14s
CI / e2e (push) Successful in 7m25s
CI / test (push) Failing after 26m49s
CI / build-android (push) Has been skipped
2026-09-07 14:32:48 +02:00
1a5731bb79 merge: rapatrie le correctif de serialisation CI (#96)
Some checks failed
CI / lint (push) Successful in 2m28s
CI / intent-service-test (push) Successful in 4m34s
CI / build (push) Successful in 1m49s
CI / e2e (push) Successful in 8m47s
CI / test (push) Failing after 37m10s
CI / build-android (push) Has been skipped
2026-09-07 14:32:31 +02:00
0447c68b69 merge: rapatrie le correctif de serialisation CI (#96)
All checks were successful
CI / lint (push) Successful in 1m49s
CI / build (push) Successful in 4m3s
CI / intent-service-test (push) Successful in 6m48s
CI / e2e (push) Successful in 13m34s
CI / test (push) Successful in 30m44s
CI / build-android (push) Has been skipped
2026-09-07 14:31:05 +02:00
f484465bee Merge pull request 'ci(test): sérialise vraiment le job test entre runs concurrents' (#96) from fix/ci-test-job-serialization into main
Some checks failed
CI / lint (push) Successful in 3m20s
CI / build (push) Successful in 3m28s
CI / intent-service-test (push) Successful in 4m39s
CI / e2e (push) Successful in 12m5s
CI / test (push) Failing after 18m6s
CI / build-android (push) Has been skipped
2026-09-07 14:30:44 +02:00
f99bf46407 chore: relance la CI (Postgres tue par un job non protege pendant l'attente)
All checks were successful
CI / lint (push) Successful in 2m23s
CI / build (push) Successful in 2m24s
CI / intent-service-test (push) Successful in 4m31s
CI / e2e (push) Successful in 7m39s
CI / test (push) Successful in 25m37s
CI / build-android (push) Has been skipped
Le nouveau step "Wait for any earlier test job" a fonctionne comme
prevu (13 tentatives, ~4m30s a attendre le job 1217, puis
"proceeding") - mais Postgres a ete coupe quasi immediatement apres
(0 passing, Can't reach database server). Cause : d'autres jobs test
en cours sur d'autres PR (#93/#94/#95, sans le correctif) executent
encore `docker rm -f postgres` sans condition au demarrage de LEUR
propre run, y compris pendant que ce job-ci utilise deja le
conteneur. Le correctif protege un job qui demarre poliment, pas
contre un job non protege qui demarre en parallele. Je laisse #93/#94/
#95 tranquilles maintenant et je ne relance que celle-ci jusqu'a ce
qu'elle passe.
2026-09-07 14:02:08 +02:00
365e7b38b7 chore: relance la CI (Postgres partage coupe en cours de run)
Some checks failed
CI / lint (push) Successful in 2m43s
CI / build (push) Successful in 3m54s
CI / intent-service-test (push) Successful in 6m10s
CI / e2e (push) Successful in 11m52s
CI / test (push) Failing after 18m30s
CI / build-android (push) Has been skipped
Can't reach database server at postgres:5432 / Server has closed the
connection - meme signature connue de contention runner que les
relances precedentes (voir ci-forgejo-runner-constraints), pas une
regression.
2026-09-07 13:45:24 +02:00
8d75462066 chore: relance la CI (Postgres partage coupe en cours de run)
Some checks failed
CI / lint (push) Successful in 2m50s
CI / test (push) Failing after 2m47s
CI / build (push) Successful in 3m24s
CI / intent-service-test (push) Successful in 5m51s
CI / e2e (push) Successful in 13m43s
CI / build-android (push) Has been skipped
Can't reach database server at postgres:5432 / Server has closed the
connection - meme signature connue de contention runner que les
relances precedentes (voir ci-forgejo-runner-constraints), pas une
regression.
2026-09-07 13:45:22 +02:00
8f75a47b23 ci(test): serialise vraiment le job test entre runs concurrents
Some checks failed
CI / lint (push) Successful in 2m47s
CI / build (push) Successful in 4m42s
CI / intent-service-test (push) Successful in 4m58s
CI / test (push) Failing after 14m15s
CI / e2e (push) Successful in 13m33s
CI / build-android (push) Has been skipped
Deux jobs `test` qui se chevauchent partagent un seul conteneur
`--name postgres` sur le reseau docker du runner (pas de bloc
`services:`) : leurs `prisma migrate deploy` + `seedReferenceData`
(beforeAll racine Mocha) rentrent en collision - "Unique constraint
failed on (key)", "No pending migrations" alors qu'il en reste,
decalages d'id tech_step/diet cassant des assertions sans rapport ;
et meme en dehors de ca ils s'affament mutuellement en RAM/CPU
(chacun entraine aussi un modele spaCy) jusqu'a ce que
resetDatabase() depasse le timeout de hook Mocha (10s) et que ca
cascade. Touche a repetition ce mois-ci (PR #47, #53, #54, et de
nouveau aujourd'hui sur #93/#94/#95), a chaque fois resolu par une
relance a vide une fois le runner plus calme - jamais un vrai bug de
la PR concernee.

`concurrency:` (le vrai correctif GitHub) est silencieusement ignore
par ce Forgejo (9.0.3, arrive en v14/Gitea 1.26). Un objet de verrou
(reseau, conteneur, fichier) fuirait : ce runner (forgejo-runner
v3.5.0) n'execute pas les steps `if: always()` suivant un step en
echec, donc pas de liberation fiable en fin de job. A la place :
s'appuyer sur ce que le runner nettoie toujours lui-meme - le
conteneur du job (supprime en succes, echec et annulation) - et
attendre tant qu'un job `test` de task id inferieur tourne encore.
Le plus petit id part en premier, donc deux jobs demarres ensemble ne
peuvent pas se bloquer mutuellement ; rien a liberer explicitement.

Trois ajouts, purement additifs (aucune ligne existante modifiee) :
- nouveau step "Wait for any earlier test job" (poll docker ps,
  plafond ~25min) juste avant le demarrage de Postgres ;
- `timeout-minutes: 45` sur le job (couvre le temps d'attente
  eventuel + garde-fou si le job reste bloque, vu l'absence de
  --exit sur Mocha) ;
- le nettoyage `docker rm -f postgres` existant balaie aussi les
  conteneurs `postgres-<suffixe>` orphelins (residus d'un essai
  anterieur de nommage par run, deja abandonne sur cette meme
  branche, jamais nettoyes faute de teardown fiable).

Travail deja fait et documente par une session precedente (branche
claude/magical-stonebraker-5dc636, verifie fonctionnel en run 130 :
"12x waiting for earlier test job(s)... puis proceeding") mais jamais
fusionne - retrouve et applique aujourd'hui en diagnostiquant la
meme contention sur trois PR en cours (#93/#94/#95).

Verification : impossible de re-simuler la course en local (pas de
second runner ici), mais le diff est purement additif et applique
sans le moindre conflit sur l'etat actuel de main - les trois commits
de ci.yml survenus depuis (upload-artifact v3, bit gradlew,
build-android) touchent un job entierement different du fichier.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 13:42:23 +02:00
022b8ed4f9 chore: relance la CI (6e collision - FK violee au seed sous contention)
Some checks failed
CI / lint (push) Successful in 3m43s
CI / intent-service-test (push) Successful in 5m52s
CI / build (push) Successful in 3m18s
CI / test (push) Failing after 13m37s
CI / e2e (push) Successful in 13m53s
CI / build-android (push) Has been skipped
Cette fois : PrismaClientKnownRequestError "Foreign key constraint
violated: tour_scenario_step_target_key_fkey" dans le beforeAll
global (seedTourScenarios). Nouvelle variante de la meme famille
connue (plusieurs process de test partageant une seule base Postgres
CI, seed concurrent) plutot qu'un nouveau bug reel - ce ticket ne
touche ni reference-seed-data.ts ni quoi que ce soit lie aux tours.
Log complet aussi montre un timeout Docker au nettoyage du conteneur
("context deadline exceeded"), signe supplementaire de charge severe
sur le runner en ce moment.
2026-09-07 13:39:09 +02:00
80c5b957d6 chore: relance la CI (Postgres partage coupe en cours de run)
Some checks failed
CI / build-android (push) Blocked by required conditions
CI / lint (push) Successful in 3m56s
CI / build (push) Successful in 3m18s
CI / intent-service-test (push) Successful in 6m29s
CI / test (push) Failing after 9m56s
CI / e2e (push) Has been cancelled
Can't reach database server at postgres:5432 / Server has closed the
connection - meme signature connue de contention runner que les
relances precedentes (voir ci-forgejo-runner-constraints), pas une
regression.
2026-09-07 13:27:46 +02:00
3cdc863774 chore: relance la CI (Postgres partage coupe en cours de run)
Some checks failed
CI / build-android (push) Blocked by required conditions
CI / lint (push) Successful in 3m20s
CI / intent-service-test (push) Successful in 4m46s
CI / build (push) Successful in 4m43s
CI / test (push) Failing after 10m16s
CI / e2e (push) Has been cancelled
Can't reach database server at postgres:5432 / Server has closed the
connection - meme signature connue de contention runner que les
relances precedentes (voir ci-forgejo-runner-constraints), pas une
regression.
2026-09-07 13:24:46 +02:00
cb3dd297a1 chore: relance la CI (contention runner - timeouts Cypress sous charge)
Some checks failed
CI / build (push) Successful in 3m16s
CI / lint (push) Successful in 3m57s
CI / intent-service-test (push) Successful in 6m18s
CI / test (push) Failing after 14m41s
CI / e2e (push) Successful in 14m0s
CI / build-android (push) Has been skipped
e2e a echoue sur des timeouts de 4s (#firstName, #houseName,
.leftovers-basket__toggle introuvables) - reproduit et verifie en local
sur cette meme branche : planning-leftovers.feature passe proprement
en 4s (2/2), aucun probleme reel. Le run CI montrait des blocs
"passing" anormalement lents partout (jusqu'a 22s pour quelques
assertions simples), signe de contention severe sur le runner pendant
que plusieurs PR tournent en parallele, pas une regression de ce
ticket.
2026-09-07 13:22:35 +02:00
63615656cc chore: relance la CI (Postgres partage coupe en cours de run)
Some checks failed
CI / build-android (push) Blocked by required conditions
CI / lint (push) Successful in 5m7s
CI / intent-service-test (push) Successful in 4m15s
CI / build (push) Successful in 3m16s
CI / test (push) Failing after 9m16s
CI / e2e (push) Has been cancelled
Can't reach database server at postgres:5432 / Server has closed the
connection - meme signature connue de contention runner que les
relances precedentes (voir ci-forgejo-runner-constraints), pas une
regression.
2026-09-07 13:05:40 +02:00
952abe8dda chore: relance la CI (4e collision infra sur le runner partage)
Some checks failed
CI / build-android (push) Blocked by required conditions
CI / lint (push) Successful in 3m33s
CI / build (push) Successful in 4m10s
CI / intent-service-test (push) Successful in 9m43s
CI / test (push) Failing after 15m14s
CI / e2e (push) Successful in 14m51s
intent-service-test a echoue cette fois sur actions/checkout lui-meme
("Non-terminating error while running 'git clone': some refs were not
updated" puis "Cannot find module '.../actions-checkout@v4/dist/index.js'")
- meme classe de collision de cache d'actions que les echecs precedents,
juste une action differente touchee cette fois (voir
ci-forgejo-runner-constraints). Ce ticket ne touche aucun fichier lie a
ces actions.
2026-09-07 13:04:04 +02:00
8d3af76328 chore: relance la CI (Postgres partage coupe en cours de run)
Some checks failed
CI / lint (push) Successful in 1m46s
CI / build (push) Successful in 3m46s
CI / intent-service-test (push) Successful in 4m30s
CI / e2e (push) Failing after 14m51s
CI / test (push) Failing after 16m7s
CI / build-android (push) Has been skipped
Can't reach database server at postgres:5432 / Server has closed the
connection - meme signature connue de contention runner que les
relances precedentes (voir ci-forgejo-runner-constraints), pas une
regression.
2026-09-07 13:02:26 +02:00
200e343cc7 chore: relance la CI (Postgres partage coupe en cours de run)
Some checks failed
CI / build-android (push) Blocked by required conditions
CI / intent-service-test (push) Failing after 36s
CI / build (push) Has been cancelled
CI / test (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / e2e (push) Has been cancelled
Can't reach database server at postgres:5432 / Server has closed the
connection - meme signature connue de contention runner que les
relances precedentes (voir ci-forgejo-runner-constraints), pas une
regression.
2026-09-07 13:02:24 +02:00
a3701acae4 fix(planning): popovers flottants surs sur mobile
Some checks failed
CI / build-android (push) Blocked by required conditions
CI / lint (push) Successful in 3m18s
CI / intent-service-test (push) Successful in 4m8s
CI / build (push) Successful in 3m42s
CI / test (push) Failing after 10m11s
CI / e2e (push) Has been cancelled
Ticket #87 du chantier UI mobile & tablette. LeftoversBasket et
WeekNavigator's CalendarPopover etaient tous les deux des popovers a
largeur fixe (18-20rem), ancres right: 0, sans aucune gestion de bord
d'ecran - sur un telephone etroit ils pouvaient deborder hors du
viewport. Les deux sont declenches depuis l'en-tete du planning, un
ecran central de l'usage quotidien - tres probablement la cause
concrete derriere le retour terrain "je n'ai pas acces a tous les
boutons" sur mobile qui a lance ce chantier.

Les deux basculent desormais sur BottomSheet (ticket #91) sous le
breakpoint phone via useIsMobileViewport() - meme contenu, juste une
autre enveloppe (le popover flottant + son ecouteur de clic exterieur
manuel restent inchanges sur desktop). Le clic-exterieur devient un
no-op propre sur mobile plutot qu'un ecouteur qui ne fait jamais rien
(le ref ne s'attache a rien dans la branche BottomSheet).

Nouvelle cle i18n common.calendar.title ("Choisir une semaine") pour
le titre de la feuille - pas de raccourci en decoupant une autre cle
interpolee.

Verifie en local : tsc -b --force, biome check, build de prod, suite
Cypress e2e complete (142/142, 2 nouveaux tests phone dans
leftovers-basket.cy.ts et planning-page.cy.ts) et composants (63/63).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 12:48:39 +02:00
d0d66bbda5 chore: relance la CI (contention runner partage sur Postgres)
Some checks failed
CI / build-android (push) Blocked by required conditions
CI / lint (push) Successful in 3m43s
CI / build (push) Successful in 3m38s
CI / intent-service-test (push) Successful in 5m52s
CI / e2e (push) Successful in 12m12s
CI / test (push) Failing after 17m13s
24 echecs melant timeouts 10s, "Unique constraint failed on the
fields: (key)" (race d'upsert concurrent au seed) et
PrismaClientInitializationError "Can't reach database server" -
combinaison connue de signatures de contention sur le Postgres partage
du runner (voir ci-forgejo-runner-constraints), pas une regression.
Ce ticket ne touche que des fichiers Cypress/apps-web, aucun code
touchant la base.
2026-09-07 12:47:11 +02:00
bb5fc825ae chore: relance la CI (collision de cache actions sur le runner)
Some checks failed
CI / lint (push) Successful in 3m22s
CI / build (push) Successful in 3m12s
CI / intent-service-test (push) Successful in 4m48s
CI / test (push) Failing after 9m15s
CI / e2e (push) Successful in 12m52s
CI / build-android (push) Has been skipped
Non-terminating error while running 'git clone' puis Cannot find
module '.../pnpm-action-setup@v4/dist/index.js' - signature connue de
collision entre deux jobs act demarrant en meme temps sur le cache
d'actions partage du runner (voir ci-forgejo-runner-constraints), pas
une regression.
2026-09-07 12:41:30 +02:00
14690134f7 chore: relance la CI (collision infra sur le Postgres partage)
Some checks failed
CI / build-android (push) Blocked by required conditions
CI / build (push) Failing after 48s
CI / e2e (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / intent-service-test (push) Has been cancelled
CI / test (push) Has been cancelled
PrismaClientInitializationError "Can't reach database server at
postgres:5432" pendant test, alors que ce ticket ne touche aucun
fichier apps/api - signature connue de contention sur le runner
partage (voir ci-forgejo-runner-constraints), pas une regression.
2026-09-07 12:38:33 +02:00
967be6df4a test(cypress): convention de viewports telephone/tablette
Some checks failed
CI / lint (push) Successful in 3m31s
CI / build (push) Successful in 2m42s
CI / intent-service-test (push) Successful in 4m51s
CI / test (push) Failing after 12m11s
CI / e2e (push) Successful in 10m50s
CI / build-android (push) Has been skipped
Ticket #83 du chantier UI mobile & tablette. Le repo n'avait aucun
override de viewportWidth/Height ni pour e2e ni pour les tests de
composants - tout tournait a la taille par defaut, jamais un vrai
telephone/une vraie tablette.

- cypress/support/viewports.ts : PHONE_VIEWPORT (390x844) et
  TABLET_VIEWPORT (900x1200), tailles Android reelles plutot que les
  presets iPhone/iPad de Cypress (appli Android uniquement) - dans les
  bandes de _breakpoints.scss ($phone/$tablet du ticket #91), pas
  collees au pixel de bordure. Commande cy.setViewport("phone" |
  "tablet") (pas de surcharge du cy.viewport natif). Importe par
  support/e2e.ts et support/component.ts, disponible dans les deux
  modes.
- layout.cy.ts : les cy.viewport(...) en dur pour du telephone (deux
  tests ajoutes par #91, plus les deux plus anciens du passage #39) et
  le test "au-dessus du point de rupture telephone" migrent vers la
  commande partagee - ce dernier passe a un vrai viewport tablette
  (900px, dans la bande 641-1024) plutot qu'un 1000x700 arbitraire,
  prouvant au passage que le preset tablette fonctionne.
- Nouveau cypress/component/Dialog.cy.tsx : premier test de Dialog en
  isolation (jusqu'ici seulement couvert indirectement via
  RecipePickerDialog) - verifie le plein-ecran sur telephone du ticket
  #91, qui n'avait pas encore son propre test, et prouve au passage que
  cy.setViewport fonctionne en mode composant.

Trouvaille en verifiant : le mode composant de Cypress a son propre
viewport par defaut, plus petit que celui du mode e2e (1000x660) - deja
sous le seuil telephone. Le premier essai du test "desktop" de Dialog
echouait pour cette raison (le CSS plein-ecran s'appliquait sans meme
appeler setViewport). Corrige en fixant un viewport large explicite
pour ce cas plutot que de compter sur un defaut implicite - note ajoutee
a dev-environment-gotchas pour la prochaine fois.

Verifie en local : tsc -b --force, biome check, build de prod, suite
Cypress e2e complete (140/140) et composants (65/65, incluant les 2
nouveaux tests de Dialog.cy.tsx).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 12:32:36 +02:00
0ecd7c1c84 Merge pull request 'feat(layout): socle UI mobile - nav, feuille et dialogs plein écran' (#92) from feat/mobile-ui-shell into main
Some checks failed
CI / lint (push) Successful in 3m13s
CI / build (push) Successful in 3m9s
CI / intent-service-test (push) Successful in 6m5s
CI / test (push) Failing after 10m19s
CI / e2e (push) Successful in 13m9s
CI / build-android (push) Has been skipped
2026-09-07 12:21:27 +02:00
d6cf4aa63d feat(mobile): redirection vers l'appli + page de telechargement
Some checks failed
CI / lint (push) Successful in 3m35s
CI / build (push) Successful in 4m33s
CI / intent-service-test (push) Successful in 4m43s
CI / e2e (push) Successful in 15m5s
CI / test (push) Failing after 15m28s
CI / build-android (push) Has been skipped
Ticket #84 du chantier UI mobile & tablette. Aucune infra de deep-link
n'existait (verifie en amont : pas de scheme personnalise, pas d'App
Links, pas d'assetlinks.json, pas de listener appUrlOpen).

- lib/mobile-app-redirect.ts : attemptOpenNativeApp() (pattern "smart
  app banner" classique - tente le scheme batchcooking://, bascule sur
  onFallback si la page est toujours visible passe un court delai) et
  isAndroidPhoneBrowser() (UA Android+Mobile, deliberement distinct de
  useIsMobileViewport() - une question de plateforme, pas de largeur).
  Respecte une preference "rester sur le web" (localStorage, cle
  exportee pour que l'onglet Parametres d'application - ticket #86 -
  la reutilise) sans jamais forcer la redirection.
- AndroidManifest.xml : nouvel intent-filter additif (scheme
  batchcooking, sans toucher au filtre MAIN/LAUNCHER existant).
- Nouvelle page /telecharger (publique, hors RequireAuth - un visiteur
  deja connecte sur le web mais sans l'appli sur cet appareil a une
  raison legitime d'y atterrir) : lien direct vers le proxy existant
  ${API_BASE_URL}/mobile/download (rien a changer cote API), bouton
  "reessayer d'ouvrir l'appli".

Deliberement pas de changement sur la landing page ici (lien discret
actuel laisse tel quel) - c'est le ticket #85, separe pour rester
petit/revuable.

Verifie en local : tsc -b --force, biome check, build de prod, suite
Cypress e2e complete (141/141 sur cette branche - #91 n'est pas encore
merge, layout.cy.ts y est donc encore dans son etat pre-#91) et
composants (69/69, incluant le nouveau mobile-app-redirect.cy.tsx).
Note technique : le premier essai de test du composant tentait un vrai
window.location.href vers le scheme personnalise depuis Cypress/
Electron, ce qui bloquait le runner indefiniment (protocole inconnu
mal gere par Electron) - corrige en rendant ce seul appel injectable
(openAppUrl, reserve aux tests) sans toucher au comportement reel.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 12:20:16 +02:00
0fd4928efc feat(layout): socle UI mobile - nav, feuille et dialogs plein ecran
All checks were successful
CI / lint (push) Successful in 51s
CI / build (push) Successful in 2m10s
CI / intent-service-test (push) Successful in 3m58s
CI / e2e (push) Successful in 8m26s
CI / test (push) Successful in 16m33s
CI / build-android (push) Has been skipped
Fondation du chantier UI mobile & tablette (#91) : jusqu'ici, toute
adaptation mobile de ce repo etait du CSS pur sur le meme DOM (aucun
composant ne branchait son JSX selon la largeur/plateforme). Ce ticket
introduit le premier vrai branchement, et les primitifs que les 8
tickets suivants du chantier reutiliseront.

- useIsMobileViewport() (apps/web/src/lib/) : point de verite unique,
  base sur matchMedia, live (reagit a un resize/une rotation).
- _breakpoints.scss : $phone/$tablet Sass + mixins phone/phone-up/
  tablet-down, remplacant les nombres magiques 640/1024 repetes en dur
  dans 6 fichiers (AppLayout, landing, recipes, recipe-picker-dialog,
  planning-page, dialog, tours-page). Les deux occurrences de 860px
  (landing hero, tours-page) sont deliberement laissees telles quelles
  - un collapse de grille 2 colonnes qui n'a rien a voir avec le
  breakpoint tablette du catalogue recettes, les unifier aurait change
  un comportement visuel reel sans raison.
- useNativeDialogBehavior : mecanique (showModal/close event/clic
  exterieur) extraite de Dialog.tsx, partagee avec le nouveau
  BottomSheet.tsx (feuille mobile plein-largeur, meme fondation
  <dialog> natif que Dialog, juste ancree en bas).
- AppLayout : sur telephone, la sidebar n'est plus reflow-ee en CSS en
  barre horizontale (l'ancien traitement) - elle est remplacee par une
  vraie barre d'onglets basse (Planning/Recettes/Liste de courses +
  Plus), le "Plus" ouvrant une BottomSheet combinant Parametres et
  Compte (deux dropdowns flottants separes cote desktop -> un seul
  point d'entree mobile, IA plus simple, un seul emplacement d'onglet).
- dialog.scss : vrai plein-ecran (bord a bord, sans arrondi) sous le
  breakpoint phone au lieu d'une marge simplement reduite.

Verifie en local : pnpm --filter web exec tsc -b --force, biome check,
pnpm --filter web build, suite Cypress e2e complete (140/140) et
composants (63/63) - y compris layout.cy.ts, reecrit pour tester la
nouvelle barre basse (l'ancien test de la barre horizontale n'a plus
de sens, ce traitement n'existe plus).

Closes #91

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 12:03:43 +02:00
94ef8b4133 Merge pull request 'fix(api): autorise l'origine WebView Capacitor dans CORS_ORIGIN' (#82) from fix/cors-origin-capacitor-app into main
All checks were successful
CI / lint (push) Successful in 2m42s
CI / build (push) Successful in 3m11s
CI / intent-service-test (push) Successful in 4m14s
CI / e2e (push) Successful in 8m41s
CI / test (push) Successful in 17m14s
CI / build-android (push) Successful in 5m5s
2026-09-07 08:39:55 +02:00
5e478188a2 fix(api): autorise l'origine WebView Capacitor dans CORS_ORIGIN
All checks were successful
CI / lint (push) Successful in 1m44s
CI / build (push) Successful in 1m44s
CI / intent-service-test (push) Successful in 4m6s
CI / e2e (push) Successful in 7m5s
CI / test (push) Successful in 15m50s
CI / build-android (push) Has been skipped
L'app Android n'arrivait a se logger/inscrire nulle part (204 +
"erreur inattendue" cote client) : CORS_ORIGIN n'etait jamais defini en
prod (docker-compose.yml ne le passe pas a `app`), donc il retombait
sur son default `http://localhost:5173` (le serveur Vite de dev), qui
ne matche evidemment jamais l'origine reelle de l'appli packagee
(`https://localhost`, cf. capacitor.config.ts). Le site web n'est lui
jamais touche : il est servi depuis la meme origine que l'API en prod,
donc jamais de preflight CORS du tout sur /auth/*.

Le symptome trompeur vient du package `cors` : un preflight OPTIONS
recoit toujours 204, meme pour une origine rejetee — la difference
invisible sans inspecter les headers est l'absence de
Access-Control-Allow-Origin, qui fait ensuite bloquer le vrai POST
cote client sans jamais atteindre le serveur. Vu depuis les logs
serveur, la route a bien l'air "appelee" (le preflight matche le meme
chemin) alors que /auth/login lui-meme n'est jamais reellement recu.

CORS_ORIGIN devient une liste separee par des virgules (le type
`ExpressServerCoreOptions.corsOrigin` acceptait deja `string | string[]`)
et son default inclut desormais `https://localhost` — l'origine de
l'appli packagee est fixe et non secrete (contrairement au domaine du
site en prod, qui n'a de toute facon pas besoin d'etre dans cette
liste puisqu'il est same-origin), donc la coder en dur dans le default
couvre tout deploiement sans configuration supplementaire.

Verifie en local : script ad hoc qui demarre le vrai `createServer()`
et envoie un preflight OPTIONS /auth/login avec differentes origines —
`https://localhost` et `http://localhost:5173` recoivent maintenant
Access-Control-Allow-Origin, une origine arbitraire non listee
continue de ne pas le recevoir (pas de bypass en wildcard). Egalement
`pnpm --filter api exec tsc --noEmit` et `pnpm exec biome check` sur
les fichiers touches.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 08:22:49 +02:00
8315f737d4 Merge pull request 'fix(auth): la déconnexion retombe sur / plutôt que /login' (#79) from fix/logout-redirect-landing into main
All checks were successful
CI / build (push) Successful in 3m4s
CI / lint (push) Successful in 3m8s
CI / intent-service-test (push) Successful in 4m54s
CI / e2e (push) Successful in 10m12s
CI / test (push) Successful in 17m13s
CI / build-android (push) Successful in 5m6s
2026-09-07 00:25:04 +02:00
21cd8f014d fix(auth): la deconnexion retombe sur / plutot que /login
All checks were successful
CI / lint (push) Successful in 3m1s
CI / build (push) Successful in 4m32s
CI / intent-service-test (push) Successful in 6m16s
CI / e2e (push) Successful in 11m28s
CI / test (push) Successful in 22m7s
CI / build-android (push) Has been skipped
RequireAuth.tsx affiche deja la LandingPage publique pour un visiteur
deconnecte exactement sur / (issue #41) — seul handleLogout naviguait
encore explicitement vers /login. Change juste la destination de
navigate() ; aucun autre changement necessaire.

Scenario Cypress mis a jour en consequence (le pas existant "the URL
should be the home page" suffit, pas besoin d'un nouveau pas).

Verifie en local, suite complete : pnpm lint, pnpm --filter web build,
pnpm run e2e (139/139, apres avoir nettoye un process vite zombie sur le
port 5173 laisse par une precedente invocation cypress dans cette meme
session — voir dev-environment-gotchas pour le detail).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 23:59:18 +02:00
6d25faa633 Merge pull request 'feat(mobile): proxie le téléchargement de l'APK via l'API (pas de CORS)' (#77) from feat/mobile-download-proxy into main
Some checks failed
CI / lint (push) Successful in 5m55s
CI / intent-service-test (push) Successful in 6m29s
CI / build (push) Successful in 6m36s
CI / test (push) Failing after 10m23s
CI / e2e (push) Successful in 13m7s
CI / build-android (push) Has been skipped
Reviewed-on: #77
2026-09-06 23:58:20 +02:00
3abb7217dd feat(mobile): proxie le telechargement de l'APK via l'API (pas de CORS)
All checks were successful
CI / lint (push) Successful in 2m59s
CI / build (push) Successful in 3m4s
CI / intent-service-test (push) Successful in 4m46s
CI / e2e (push) Successful in 9m33s
CI / test (push) Successful in 17m20s
CI / build-android (push) Has been skipped
Suite au fix de /releases/latest (precedent), l'utilisateur voulait un
lien qui declenche le telechargement du .apk directement, sans quitter
l'appli web. Verifie en direct : fetch("https://git.dev.kyuno.fr/api/...")
depuis le navigateur echoue avec "Failed to fetch" (confirme via un essai
en mode no-cors : la requete reseau aboutit bien, seule la reponse est
bloquee) — Forgejo n'envoie aucun header CORS sur son API Releases,
publique ou non. Ca ne concerne pas que la page d'accueil : le hook de
verification de mise a jour (#66, useAppUpdateCheck) faisait exactement le
meme fetch cross-origin depuis la WebView native, et echouait donc tout
aussi silencieusement en production sans que personne ne puisse s'en
rendre compte (le hook avale toute erreur reseau par design).

Ajoute un petit module apps/api/src/modules/mobile/ (2 routes publiques,
aucune ne touche la base de donnees) :
- GET /mobile/latest-release -> { version } (proxy JSON, remplace le fetch
  direct de useAppUpdateCheck)
- GET /mobile/download -> redirection 302 vers l'asset .apk reel de la
  derniere release (ou vers la page /releases/latest en repli si
  Forgejo est injoignable ou qu'aucun .apk n'est encore attache)

Cote frontend : LandingPage.tsx et UpdateBanner.tsx pointent maintenant
vers ce proxy (`${API_BASE_URL}/mobile/download`, target="_blank") au lieu
d'une URL Forgejo directe — un clic, telechargement immediat, jamais de
navigation hors de l'appli. useAppUpdateCheck.ts appelle desormais
apiClient.getLatestMobileVersion() au lieu d'un fetch direct.

Verifie en local (sans Postgres, ces routes n'en ont pas besoin) contre
les vraies donnees Forgejo :
  GET /mobile/latest-release -> {"version":"v0.2.0"}
  GET /mobile/download -> 302, Location vers le vrai .apk signe

pnpm lint / tsc (api + web) / pnpm --filter web build : tous verts. Le
scenario Cypress "offers the Android app download" echoue encore en local
(meme souci pre-existant deja documente sur la PR precedente, confirme
independant du code par CI reel) ; mis a jour pour asserter le nouveau
href relatif.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 23:40:06 +02:00
7cbd4944bd Merge pull request 'fix(mobile): corrige les liens vers /releases/latest/download' (#76) from fix/forgejo-latest-release-url into main
All checks were successful
CI / lint (push) Successful in 2m45s
CI / build (push) Successful in 2m48s
CI / intent-service-test (push) Successful in 4m36s
CI / e2e (push) Successful in 9m20s
CI / test (push) Successful in 17m21s
CI / build-android (push) Successful in 5m12s
2026-09-06 22:21:37 +02:00
29bd413de3 fix(mobile): corrige les liens vers /releases/latest/download
All checks were successful
CI / lint (push) Successful in 3m3s
CI / build (push) Successful in 3m15s
CI / intent-service-test (push) Successful in 4m28s
CI / e2e (push) Successful in 9m31s
CI / test (push) Successful in 17m39s
CI / build-android (push) Has been skipped
Verifie en conditions reelles apres le premier vrai succes de bout en
bout de release.yml (v0.2.0, Release Forgejo #12 avec batchcooking.apk
attache) : Forgejo, contrairement a GitHub, n'implemente pas le
raccourci /releases/latest/download/<fichier>. Seul /releases/latest
lui-meme resout (redirige vers la page de la release) :

  /releases/latest/download/batchcooking.apk -> 404
  /releases/latest                            -> 303 vers /releases/tag/v0.2.0 (OK)
  /releases/download/v0.2.0/batchcooking.apk  -> 200 (OK, mais pas "latest")

Corrige les deux endroits qui presumaient le raccourci GitHub (issue #65
et #66, deja mergees) pour pointer vers /releases/latest tout court : un
clic de plus via la page de release Forgejo pour atteindre le fichier,
mais un lien qui resout toujours plutot qu'un raccourci qui 404 en
permanence. Met a jour le test Cypress de la page d'accueil et le
commentaire de release.yml en consequence.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 22:03:14 +02:00
da3d080124 Merge pull request 'fix(release): installe curl avant les appels API de forgejo-release' (#75) from fix/forgejo-release-curl-install into main
All checks were successful
CI / lint (push) Successful in 3m4s
CI / build (push) Successful in 4m19s
CI / intent-service-test (push) Successful in 8m12s
Release / sanity-build (push) Successful in 10m22s
CI / e2e (push) Successful in 14m30s
Release / build-android-apk (push) Successful in 9m15s
Release / forgejo-release (push) Successful in 28s
Release / notify-portainer (push) Successful in 2s
CI / test (push) Successful in 15m3s
CI / build-android (push) Successful in 4m55s
2026-09-06 21:24:02 +02:00
7d4e7efcce fix(release): installe curl avant les appels API de forgejo-release
All checks were successful
CI / lint (push) Successful in 2m58s
CI / intent-service-test (push) Successful in 4m17s
CI / build (push) Successful in 4m28s
CI / e2e (push) Successful in 9m9s
CI / test (push) Successful in 17m36s
CI / build-android (push) Has been skipped
3e vrai declenchement de release.yml (tag v0.2.0) : forgejo-release
echoue en 25s avec 'curl: command not found' — meme classe de probleme
que le docker manquant deja corrige pour sanity-build (#73) : ce runner
ne fournit pas ces outils par defaut, ci.yml's test job avait deja du
installer curl explicitement pour la meme raison.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 21:05:48 +02:00
f6e501d7b5 Merge pull request 'fix(release): remplace softprops/action-gh-release par l'API Forgejo native' (#74) from fix/forgejo-release-native-api into main
Some checks failed
CI / lint (push) Successful in 4m13s
CI / build (push) Successful in 3m28s
CI / intent-service-test (push) Successful in 6m51s
Release / sanity-build (push) Successful in 11m18s
CI / e2e (push) Successful in 15m16s
Release / build-android-apk (push) Successful in 9m38s
CI / test (push) Failing after 21m38s
CI / build-android (push) Has been skipped
Release / forgejo-release (push) Failing after 25s
Release / notify-portainer (push) Has been skipped
2026-09-06 20:42:03 +02:00
8693498373 fix(release): remplace softprops/action-gh-release par l'API Forgejo native
All checks were successful
CI / lint (push) Successful in 2m57s
CI / build (push) Successful in 2m59s
CI / intent-service-test (push) Successful in 4m14s
CI / e2e (push) Successful in 9m19s
CI / test (push) Successful in 17m23s
CI / build-android (push) Has been skipped
2e vrai declenchement de release.yml (tag v0.2.0, apres le fix du docker
manquant sur sanity-build) : forgejo-release echoue en 35s. Log complet :

  Creating new GitHub release for tag v0.2.0...
  GitHub release failed with status: 405
  (x3, puis "Too many retries. Aborting...")

Pas un souci de ref bare comme les autres actions de ce fichier (deja
corrige) : la requete de creation de release elle-meme repond 405 cote
Forgejo, une vraie incompatibilite d'API entre les deux plateformes sans
contournement connu cote configuration de softprops/action-gh-release.

Remplace ce step par deux appels directs a l'API REST native de Forgejo
(POST /repos/.../releases puis POST .../releases/{id}/assets) avec le
GITHUB_TOKEN deja fourni par le runner (permissions: contents: write
deja declare en tete de fichier) — evite toute dependance a la
compatibilite GitHub-Forgejo d'une action tierce. Pas d'equivalent a
generate_release_notes ici (fonctionnalite propre a GitHub, non repliquee
par Forgejo) : le corps de la release reste minimal.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 20:23:48 +02:00
aeea0810cc Merge pull request 'fix(release): installe docker avant le build de sanity-build' (#73) from fix/sanity-build-docker into main
Some checks failed
CI / lint (push) Successful in 7m2s
CI / intent-service-test (push) Successful in 4m19s
CI / build (push) Successful in 3m12s
Release / sanity-build (push) Successful in 9m26s
CI / e2e (push) Successful in 11m39s
Release / build-android-apk (push) Successful in 9m48s
Release / forgejo-release (push) Failing after 35s
Release / notify-portainer (push) Has been skipped
CI / test (push) Failing after 20m59s
CI / build-android (push) Has been skipped
2026-09-06 19:57:57 +02:00
6d868809ac fix(release): installe docker avant le build de sanity-build
All checks were successful
CI / lint (push) Successful in 4m30s
CI / intent-service-test (push) Successful in 6m22s
CI / build (push) Successful in 3m15s
CI / e2e (push) Successful in 8m54s
CI / test (push) Successful in 20m1s
CI / build-android (push) Has been skipped
Premier vrai declenchement de release.yml (tag v0.2.0) : sanity-build
echoue en 17s avec 'docker: command not found' — ce runner Forgejo
self-hoste ne fournit pas docker par defaut dans les conteneurs de job,
meme constat deja rencontre par le job test de ci.yml qui l'installe
explicitement avant ses propres appels docker. sanity-build ne l'avait
jamais fait, presque certainement jamais reellement execute sur ce runner
depuis la migration vers Forgejo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 19:36:38 +02:00
ce168a758c Merge pull request 'fix(release): corrige release.yml pour Forgejo et y attache un APK signé' (#72) from fix/release-yml-forgejo into main
Some checks failed
CI / lint (push) Successful in 2m42s
Release / sanity-build (push) Failing after 17s
CI / build (push) Successful in 2m52s
CI / intent-service-test (push) Successful in 4m57s
CI / test (push) Failing after 10m56s
Release / build-android-apk (push) Successful in 11m48s
CI / e2e (push) Successful in 12m3s
Release / forgejo-release (push) Has been skipped
Release / notify-portainer (push) Has been skipped
CI / build-android (push) Has been skipped
2026-09-06 19:15:55 +02:00
854d795c5d fix(release): corrige release.yml pour Forgejo et y attache un APK signe
All checks were successful
CI / lint (push) Successful in 2m55s
CI / build (push) Successful in 2m58s
CI / intent-service-test (push) Successful in 4m48s
CI / e2e (push) Successful in 9m34s
CI / test (push) Successful in 17m24s
CI / build-android (push) Has been skipped
release.yml datait d'avant la migration vers Forgejo et n'avait jamais ete
reteste : refs d'action bares (actions/checkout@v4, softprops/action-gh-
release@v2) sans le prefixe URL complet qu'exige ce runner self-hosted
(meme contrainte deja rencontree et documentee dans ci.yml).

Ajoute aussi ce que #65 attendait reellement : un job build-android-apk
(meme recette que le job build-android de ci.yml, issue #64) qui construit
et signe l'APK, deduit versionName/versionCode du tag pousse (vX.Y.Z ->
versionName X.Y.Z, versionCode majeur*10000+mineur*100+correctif) et
l'attache a la Release Forgejo sous un nom de fichier stable
(batchcooking.apk) via softprops/action-gh-release. C'est ce nom stable qui
permet a /releases/latest/download/batchcooking.apk (page d'accueil, #65)
de toujours pointer vers la derniere release sans jamais changer de lien.

build.gradle : versionCode/versionName deviennent surchargeables via
-PandroidVersionCode/-PandroidVersionName (defaut inchange : 1 / "1.0"
pour tout build qui ne passe pas ces proprietes, comme le job
build-android existant de ci.yml sur un simple push main).

Duplique le job de build Android plutot que de factoriser en workflow_call
reutilisable — le support des workflows reutilisables sur ce runner
Forgejo/act self-hoste n'est pas verifie, et cette recette de ~15 lignes
est deja eprouvee telle quelle dans ci.yml ; pas la peine de risquer une
nouvelle surprise de compatibilite pour economiser un peu de duplication.

Non teste de bout en bout dans cette PR : release.yml ne se declenche que
sur un vrai tag pousse (jamais sur une simple branche/PR), et pousser un
tag ici declencherait potentiellement un vrai redeploiement Portainer en
production si PORTAINER_WEBHOOK_URL est deja configure — a tester
deliberement avec l'utilisateur, pas par un tag de test improvise.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 18:57:33 +02:00
372988d734 Merge pull request 'fix(ci): retombe sur upload-artifact v3 (v4+ non supporté par ce Forgejo)' (#71) from fix/upload-artifact-ghes-compat into main
All checks were successful
CI / lint (push) Successful in 2m57s
CI / build (push) Successful in 3m19s
CI / intent-service-test (push) Successful in 4m23s
CI / e2e (push) Successful in 9m20s
CI / test (push) Successful in 17m41s
CI / build-android (push) Successful in 5m14s
2026-09-06 18:19:15 +02:00
998f0ac6bc fix(ci): retombe sur upload-artifact v3 (v4+ non supporté par ce Forgejo)
All checks were successful
CI / lint (push) Successful in 2m9s
CI / build (push) Successful in 2m25s
CI / intent-service-test (push) Successful in 4m34s
CI / e2e (push) Successful in 7m22s
CI / test (push) Successful in 16m44s
CI / build-android (push) Has been skipped
Le tout premier build-android complet et signé (keystore enfin correct)
échouait quand même à la toute dernière étape :

  GHESNotSupportedError: @actions/artifact v2.0.0+, upload-artifact@v4+
  et download-artifact@v4+ ne sont pas actuellement supportés sur GHES.

v4+ exige l'API "Results" propre à github.com — non implémentée par ce
runner Forgejo self-hosted. v3 utilise encore l'ancienne API Artifacts,
seule compatible ici ; l'interface name/path utilisée par ce job est
identique entre les deux versions, aucun autre changement nécessaire.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 18:01:34 +02:00
27d82b49ca chore: relance la CI (test du nouveau keystore Android)
Some checks failed
CI / lint (push) Successful in 2m54s
CI / build (push) Successful in 2m56s
CI / intent-service-test (push) Successful in 4m48s
CI / e2e (push) Successful in 9m33s
CI / test (push) Successful in 17m22s
CI / build-android (push) Failing after 4m56s
Commit vide (aucun fichier modifie) — declenche le pipeline push sur main
pour verifier le nouveau secret ANDROID_KEYSTORE_BASE64 fourni par
l'utilisateur, ci.yml n'ayant pas de declenchement manuel (workflow_dispatch).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 16:56:53 +02:00
644164b25a Merge pull request 'feat(landing): lien de téléchargement de l'app Android (#65)' (#68) from feat/landing-apk-download into main
Some checks failed
CI / lint (push) Successful in 2m54s
CI / build (push) Successful in 2m58s
CI / intent-service-test (push) Successful in 5m7s
CI / e2e (push) Successful in 9m32s
CI / test (push) Successful in 17m30s
CI / build-android (push) Failing after 5m6s
2026-09-06 16:18:09 +02:00
966a0afa02 chore: relance la CI (#68)
All checks were successful
CI / lint (push) Successful in 47s
CI / build (push) Successful in 1m56s
CI / intent-service-test (push) Successful in 3m46s
CI / e2e (push) Successful in 7m40s
CI / test (push) Successful in 17m12s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 16:00:32 +02:00
68216cf852 Merge pull request 'fix(ci): corrige le bit exécutable de gradlew et le fiabilise en CI' (#70) from fix/gradlew-executable-bit into main
Some checks failed
CI / lint (push) Successful in 2m11s
CI / build (push) Successful in 2m26s
CI / intent-service-test (push) Successful in 4m2s
CI / e2e (push) Successful in 7m29s
CI / test (push) Successful in 16m30s
CI / build-android (push) Failing after 4m54s
2026-09-06 15:27:32 +02:00
9c6feab064 fix(ci): corrige le bit exécutable de gradlew et le fiabilise en CI
All checks were successful
CI / build (push) Successful in 3m5s
CI / lint (push) Successful in 3m12s
CI / intent-service-test (push) Successful in 4m16s
CI / e2e (push) Successful in 9m3s
CI / test (push) Successful in 17m43s
CI / build-android (push) Has been skipped
Le tout premier run réel du job build-android (après le merge de #64)
échouait avec './gradlew: Permission denied' — gradlew était suivi par
git en 100644 (non exécutable) au lieu de 100755, probablement perdu au
commit initial du projet Android natif (#63) sur cette machine Windows.

Corrige le mode suivi par git (git update-index --chmod=+x) et ajoute un
chmod +x défensif juste avant l'exécution dans ci.yml, puisque ce bit
n'a aucun sens sous Windows et peut être reperdu silencieusement par un
futur commit sur cette machine.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 15:09:21 +02:00
c0a07e8adc Merge pull request 'feat(ci): build, teste et empaquette un APK Android signé sur chaque push main' (#67) from feat/mobile-ci-android-apk into main
Some checks failed
CI / lint (push) Successful in 2m48s
CI / build (push) Successful in 2m51s
CI / intent-service-test (push) Successful in 4m9s
CI / e2e (push) Successful in 9m14s
CI / test (push) Successful in 17m18s
CI / build-android (push) Failing after 4m15s
2026-09-06 14:44:35 +02:00