Aller au contenu
Candidater

Journal des modifications

Les évolutions de Cohez.io, de la plus récente à la plus ancienne.

14 versions correspondent à « réunion ».

Versions 1 à 10 sur 14

0.25.6.0 — 2026-09-28

Ajouts

  • Page d'erreur applicative en français sur les espaces association (#318, 2026-09-26). Les 403, 404, 410 (et les 500 hors mode debug) des sous-domaines tenant affichent une page Inertia du Design System (errors/HttpError) au lieu de la page Laravel en anglais : titre et message par statut, bouton « Retour au tableau de bord » réservé aux utilisateurs connectés. Le 410 reste générique (« Ce lien ou ce document n'est plus disponible ») car il couvre aussi les liens publics expirés du funnel. Seul le code de statut est transmis à la page : ni message d'exception, ni chemin, ni trace. La vitrine, l'admin Filament et les réponses JSON gardent leur comportement d'origine ; si le rendu échoue, l'erreur est journalisée et la réponse d'origine est renvoyée.

Modifications

  • Contraste AA des couleurs de statut success et warning, dans toute l'application (#318, 2026-09-26). Blanc sur #27AE60 ou #C68C00 plafonnait à 2,9:1 ; les tokens passent à #1F7A3E et #8A6100 en clair (≥ 5:1 sous texte blanc et sur le fond de page), avec un texte foncé sur les badges en sombre. Tous les badges, pastilles et textes de statut changent de teinte (Dashboard, paniers, inscriptions, réunions, toasts).
  • Accessibilité de l'onglet Santé et de la page Archives santé (#318, 2026-09-26). Formats, taille maximale et plage de dates acceptés affichés sous le champ de dépôt, dérivés des règles serveur ; champ fichier vidé après un dépôt réussi ; boutons « Déposer » / « Enregistrer » actifs, validation à la soumission, erreurs annoncées (role="alert") et focus sur le premier champ en erreur ; erreur de saison reliée au sélecteur. Archives : titres de tableaux (<caption>), aide du motif reliée au champ, état de téléchargement. Icônes décoratives masquées aux lecteurs d'écran, noms accessibles distincts d'une saison à l'autre, mention « nouvel onglet », cibles tactiles de 44 px sur mobile.
  • Composants de formulaire (#318, 2026-09-26). Input, Textarea et Select ne posent aria-describedby que si l'aide ou l'erreur visée existe ; Select accepte une aide et une erreur reliées, et aligne sa valeur à gauche partout.

Corrections / Sécurité

  • Les pièces santé sont téléchargées avec leur vrai type de fichier (#318, 2026-09-26). StreamMemberDocument ne posait pas de Content-Type : la pièce partait en text/html. Elle est maintenant servie en PDF, JPEG ou PNG selon son extension (liste blanche, repli application/octet-stream), avec X-Content-Type-Options: nosniff. Formats acceptés, attribut accept, aide affichée et type servi viennent d'une source unique, HealthDocumentRules.
  • Page d'erreur applicative : correctifs de revue (#318, 2026-09-26). L'admin sur admin.{domaine} garde sa page d'origine même si ADMIN_DOMAIN diffère ; une réponse d'erreur déjà en JSON n'est jamais remplacée par la page HTML ; tous les appels fetch JSON du front (funnel public, groupes, utilisateurs, représentants légaux, réunion live) envoient Accept: application/json, pour recevoir le message d'erreur du serveur plutôt qu'une page ; un visiteur sans session (URL inexistante) se voit proposer « Retour à l'accueil ». Une fiche introuvable (404 levé à la résolution du modèle de la route, par exemple /members/{id} inconnu) garde l'utilisateur connecté et le nom de l'association : les middlewares Inertia passent désormais avant SubstituteBindings.
  • Onglet Santé et Archives : erreurs mieux rattachées (#318, 2026-09-26). L'erreur sur le représentant légal d'une attestation est affichée et reliée à son champ, et une erreur sans champ dédié est annoncée au niveau du formulaire. Dans les Archives, une pièce déjà supprimée (410), une erreur réseau ou un refus serveur s'affichent dans le dialogue sans marquer le motif invalide ; l'erreur « motif trop court » s'efface à la saisie.
  • Stack Docker de dev : healthcheck nginx limité à /health exact (#322, 2026-09-28). location /health était un préfixe et interceptait /health-archives, qui répondait healthy au lieu d'afficher la page Archives santé en local. Aucun effet sur Clever Cloud.

0.25.0.0 — 2026-09-04

Ajouts

  • Le registre des salariés existe, et un salarié peut participer à une réunion sans qu'on lui fabrique une fiche d'adhérent (#277, 2026-09-02). Nouvelle table employees et pivot employee_employee_types — un salarié cumule plusieurs types —, enums EmployeeType et EmployeeStatus, EmployeePolicy, pages Inertia Employees/Index|Show|Form. users.employee_id (nullable) relie un compte à sa fiche RH ; meeting_participants.person_id ajoute un quatrième mode de participation, mutuellement exclusif des trois autres. Un rôle coach et une permission view_own_courses ouvrent un calendrier en lecture seule, vers lequel la connexion redirige directement : il n'expose que les métadonnées des cours, aucune donnée personnelle d'adhérent.
  • Les comptes user_type = 'employee' sans fiche RH sont listés sur le registre, en mode dégradé (#280, 2026-09-02). EmployeeController::index() expose unlinkedStaff — les comptes du tenant dont employee_id est nul —, rendus avec un badge « Sans fiche RH » et un bouton « Créer la fiche ». Aucune donnée n'est écrite et aucun backfill n'est lancé : c'est un révélateur d'un écart existant, pas une migration. Le formulaire ne pré-remplit person_id que si un seul persons.email correspond (comparaison en minuscules, en une requête, sans N+1). La section disparaît dès qu'un filtre de statut est posé, et au-delà de la première page, où elle n'aurait plus de sens.
  • Kit de formation EPGV 44 et profils de règlement du jeu de démonstration (#273, 2026-08-27). Docs/Formations/EPGV-44/ reçoit un déroulé animateur, des fiches pratiques et un support projeté. Côté données, EpgvSeeder répartit les inscriptions sur des profils de règlement contrastés — 7 soldées, 2 partielles, 1 chèque annoncé mais non encaissé, 2 sans aucun paiement — pour que le tableau de bord de démonstration affiche 3 impayés plutôt qu'un jeu uniformément soldé, qui ne montrait aucun des écrans de relance. createPaymentReceived() et createPaymentPending() acceptent désormais des paramètres optionnels.
  • Comptes et réunion de formation du tenant demo-epgv-44 (#275, 2026-08-27). Six comptes admin (mot de passe password), un helper createEmployeeUser(), et la réunion « Présentation et formation Cohézio » avec ses six participants : la démonstration part d'un tenant peuplé au lieu d'écrans vides.

Corrections

  • Les compteurs du tableau de bord ignoraient le statut des inscriptions (#278, 2026-09-01). seasonRegistrations, unpaidCount et unpaidMembers passent par deux helpers privés qui appliquent whereNotIn('status', RegistrationStatus::terminalStatuses()). Mesuré sur une copie de la production : 527 inscriptions de saison annoncées pour 467 réelles, et 69 impayés annoncés pour 13. Un dirigeant relançait donc cinq fois trop de monde. collectedAmount n'est volontairement pas filtré : un paiement received reste encaissé après l'annulation de l'inscription qui l'a motivé — ne pas « compléter » ce correctif en l'y ajoutant.
  • Une inscription annulée interdisait toute réinscription du même membre sur la même campagne (#279, 2026-09-03). La contrainte UNIQUE totale (member_id, campaign_id) est remplacée par un index unique partiel, where status not in ('cancelled', 'abandoned'). Mesuré sur lezards-animes : 60 couples (membre, campagne) ne portaient plus que des inscriptions annulées — 60 personnes bloquées, avec un SQLSTATE 23505 pour seule explication. RegistrationDuplicateChecker est aligné sur terminalStatuses() ; c'est un no-op fonctionnel aujourd'hui, la méthode ne rendant que cancelled — l'index partiel EST le correctif. abandoned est nommé d'avance à dessein : status est un varchar(255) et non un enum PostgreSQL, l'ajouter à terminalStatuses() suffira le jour venu.
  • Findings de la revue de code du registre des salariés (#281, 2026-09-02). Treize sur quatorze corrigés. Le tableau de bord vide désormais unpaidMembers, recentActivity et closingSoonCampaigns côté serveur pour les rôles sans view_members : un coach recevait la charge utile complète et on ne comptait que sur le front pour ne pas l'afficher. mapPerson() est réduit à id / prénom / nom / e-mail, avec un test qui fige la forme exacte de la charge utile (sans etc()), pour qu'un champ rajouté fasse rougir la suite. Sont également corrigés : la double invitation sur une même fiche salarié, l'unicité d'un participant par réunion, l'eager-load de participants.person dans GenerateMeetingReportJob, le plafonnement de unlinkedStaff(), la validation d'employee_id en query-string comme UUID du tenant, et la seconde sortie de connexion de Fortify — celle du 2FA — qui ne redirigeait pas le coach.
  • La liste des adhérents annonçait « En attente » à des adhérents dont l'adhésion court (#283, 2026-09-04). Le badge et la pilule de filtre portant l'axe administratif (members.status) sont retirés de members/Index.vue et de MemberFilters.vue ; il ne reste que l'état dérivé des périodes de memberships. Motif : aucun écran n'écrit cette colonne — ni la création, ni le formulaire d'édition, et les boutons Désactiver / Réactiver touchent is_active —, si bien qu'elle restait figée sur sa valeur de création. Le trou est dans le front, pas dans le domaine : Member::changeStatus(), UpdateMemberUseCase et la route members.update-status savent l'écrire dès que la charge utile porte le champ. Le paramètre status reste donc honoré côté serveur et applyFilters le reconduit d'une requête à la suivante, sans quoi un signet le portant n'aurait survécu qu'à un seul chargement. PersonMemberTab.vue affiche encore le badge hérité : hors périmètre, connu. MembersLegacyStatusAxisHiddenTest verrouille le retrait sur le source — le réexposer suppose d'abord qu'un écran pose la valeur.

Notes techniques

  • Cette version est d'abord un rattrapage de documentation. Les sept premières PR ci-dessus sont parties en production entre le 27 août et le 3 septembre 2026 sans commit de release ; chacune est datée de son merge. Seule #283 est livrée par cette version : elle n'était pas déployée quand ce fichier a été écrit, et c'est pour ne pas reproduire le retard de documentation qu'il vient de combler qu'elle y figure. Les sept premières sont regroupées sous un seul numéro plutôt que réparties sur des versions intermédiaires que VERSION n'a jamais portées et qu'aucun déploiement n'a servies. Le segment mineur bouge parce que le registre des salariés ajoute des tables et un module.
  • Course::coachEmployee() a été renommée findActiveCoachEmployee(), et ce n'est pas cosmétique. Une méthode au nom de relation qui rend un Employee au lieu d'une Relation fait appeler getResults() par Eloquent dès qu'un eager-load ou un accès en propriété la croise : erreur fatale, pas avertissement.
  • Le down() de la migration de l'index partiel lève une RuntimeException. Restaurer une contrainte UNIQUE totale échouerait dès qu'un couple (membre, campagne) porte une inscription annulée et une active — soit exactement ce que cette version rend possible. La migration est à considérer comme irréversible en production.
  • recentActivity() n'est toujours pas filtré par statut : les inscriptions annulées continuent d'y figurer. Connu, hors périmètre de #278, à traiter avant que la saison 2026-2027 passe Active.
  • Employees/Form.vue expose encore person_id en UUID brut. Connu, non corrigé : le champ attend un sélecteur de personne.
  • Les PR #225, #237 et #266 à #269 ne sont listées nulle part ici : toutes ont été mergées entre le 21 et le 24 août 2026, donc hors de la fenêtre couverte par cette version. #225 et #237 sont par ailleurs des montées de dépendances Dependabot, que ce fichier ne détaille jamais — il documente l'activation de Dependabot et les gates de CI, pas les bumps individuels ; #266 à #269 sont des changements internes sans effet sur l'application (fichiers temporaires Livewire ignorés, notes de roadmap, retrait des références JetBrains, discipline de workflow).

0.19.4.0 — 2026-07-17

Ajouts

  • Éditeur WYSIWYG pour le compte-rendu de réunion en brouillon (MeetingReportEditor.vue, Tiptap v3) : remplace le <Textarea> markdown brut par un éditeur riche (titres, listes, tableaux, citations, code, images, liens) tout en conservant content en markdown en base — aucun changement de schéma. Le PDF et l'e-mail du compte-rendu stylent désormais tableaux, citations et blocs de code au même format.

Corrections

  • Préservation des images markdown dans l'éditeur WYSIWYG du CR (round-trip édition ↔ sauvegarde).
  • Liens javascript: neutralisés dans le rendu markdown du PDF du CR (allow_unsafe_links: false, alignement avec l'e-mail).
  • Taille maximale du contenu du compte-rendu (100 000 caractères) désormais appliquée côté serveur.

0.19.3.0 — 2026-07-15

Ajouts

  • Affichage de l'ordre du jour sur la fiche réunion (Show.vue) : chaque point de l'ordre du jour est désormais rendu (badge Traité/En attente, décision si renseignée, actions avec responsable résolu — utilisateur lié ou nom libre, échéance formatée). Auparavant la Card titrée « Ordre du jour » affichait en réalité meeting.description (mislabel) ; cette section est renommée « Notes ». Le contrôleur charge désormais agendaItems.actions.responsible en eager-load, et MeetingAgendaItem expose status/status_label en attributs calculés.
  • Compte-rendu de réunion généré par IA (Mistral) : à la clôture, le CR est désormais généré en arrière-plan par GenerateMeetingReportJob — synthèse IA (MeetingReportSynthesizer) en chemin nominal, secours automatique sur le template déterministe existant en cas d'échec (timeout, erreur API), sans jamais bloquer ni faire échouer la clôture elle-même. La clôture (close()) devient elle-même atomique et idempotente (garde status != completed), tout comme la nouvelle action d'annulation d'une séance en cours (cancelLive(), POST /meetings/{id}/cancel-live) qui permet de revenir de live à scheduled en cas d'erreur de manipulation.
  • Page de conduite en direct repensée (Live.vue) : navigation par onglets (Ordre du jour / Notes / Transcription), notes de séance libres autosauvées (PATCH /meetings/{id}/notes) remplaçant l'ancienne saisie décision/action point par point, et chronomètre de séance qui survit désormais à un rechargement de page (started_at persisté).
  • Champs lieu distant et téléphone sur les réunions (meeting_link, phone) : une réunion peut désormais porter un lien de visioconférence et/ou un numéro d'appel, affichés sur la fiche et dans le formulaire.
  • Garde-fou séance bloquée : une commande planifiée quotidienne (meetings:notify-stuck-live, 08:00 Europe/Paris) détecte les réunions restées live plus de 2h après leur ends_at et notifie l'organisateur par email (MeetingStuckLiveMail) — notification uniquement, aucune mutation automatique de statut ou de données.

0.19.2.0 — 2026-07-15

Modifications

  • Simplification de l'ordre du jour des réunions : les points de l'ordre du jour perdent la durée estimée, le responsable dédié et les horodatages de démarrage/clôture (estimated_duration_minutes, responsible_user_id, started_at, ended_at), remplacés par un champ description libre. La progression pendant la conduite en direct (pending/actif/terminé) est désormais suivie côté client, sans persistance par point.

Corrections

  • Garde de transition Draft → Live : l'ouverture de la page Live (GET /meetings/{id}/live) ne transitionne plus que les réunions scheduled vers live ; une réunion draft ouverte directement en Live reste draft au lieu d'être basculée à tort.

0.14.0.0 — 2026-05-29

Ajouts

  • Gestion des documents officiels de l'association : les administrateurs peuvent désormais déposer et supprimer les statuts et le règlement intérieur depuis les paramètres de l'association. Les documents sont stockés de façon privée sur S3 (Clever Cloud Cellar) avec des URLs temporaires signées (30 min). Un seul document actif par type est conservé ; un nouvel upload archive automatiquement le précédent.
  • Consultation des documents depuis le formulaire public d'inscription : quand un document officiel est disponible, un lien « Lire les statuts » / « Lire le règlement intérieur » apparaît dans le formulaire d'inscription (étape Identité). Le lien reste accessible même si la campagne est clôturée, mais expire avec le token d'inscription.
  • Audit de cohérence S3/DB (php artisan documents:audit) : commande hebdomadaire qui détecte et peut supprimer (--delete) les fichiers orphelins présents sur S3 mais absents de la base de données.

Corrections

  • ConfirmDialog : suppression silencieuse sur toute l'application : ConfirmDialog.vue émettait update:open(false) avant confirm, ce qui effaçait l'identifiant de la ressource à supprimer avant que le handler parent ne soit exécuté. La suppression ne déclenchait jamais la requête serveur. Correction : confirm est émis en premier. Ce bug affectait les 17+ utilisations de ConfirmDialog dans l'app (membres, groupes, réunions, documents, etc.).
  • Liens documents non cliquables dans le formulaire d'inscription public : les liens « Lire les statuts / règlement » utilisaient le composant <Link> d'Inertia qui appelle preventDefault(), empêchant l'ouverture du PDF. Rétablis en <a target="_blank">.

0.13.2.1 — 2026-05-25

Modifications

  • Documentation synchronisée avec le code : audit complet de Docs/ — corrections des décalages entre la documentation et l'implémentation réelle (enum PaymentMethod, statut Abandoned, champ reply_to_email vs email, contrainte rna VARCHAR(10), format registration_ids dans les exemples HelloAsso, champ transcript des réunions, routes actives des membres). Le fichier Docs/Development/Multi-Tenant-TODOs.md est archivé dans Docs/Archive/.
  • Plans et specs gstack déplacés hors dépôt : les fichiers de planification générés par les outils IA (Docs/superpowers/) sont désormais stockés hors du dépôt et n'apparaissent plus dans les diffs de PR.

0.5.5.0 — 2026-04-30

Ajouts

  • WaterPoloSeeder : seeder de démo pour l'association "Cholet Water-Polo" (demo-cholet-waterpolo), support de la démo alpha pour Laurent LECLERC (DG) et Charles PRÉVOST (trésorier). Crée un environnement complet de club aquatique : 70 membres (4 bureau avec comptes admin, 8 membres expirés 2024-2025, 26 adultes solo, 8 familles Cas 1 avec enfants, 4 familles Cas 2 avec parent non-membre), 3 cours actifs 2025-2026 (Adultes lundi+mercredi, U18 mardi+samedi, Jeunes mercredi+samedi) avec créneaux horaires et coach salarié, rubrique de cotisation FFN-compatible (adulte 85€, jeune 55€, dirigeant 40€) avec remise famille −10%, 3 groupes organisationnels (Bureau, Section Adultes, Section Jeunes), et 4 réunions de bureau (3 clôturées avec CRs + 1 planifiée). Le seeder est idempotent et recrée uniquement les réunions via refreshDemoMeetings() si l'association existe déjà.

0.5.4.0 — 2026-04-30

Ajouts

  • EpgvSeeder : seeder de démo pour l'association "EPGV 44 — Vitafédé" (demo-epgv-44), utilisé pour le comité directeur du 19 mai 2026. Crée un environnement de démo complet : 4 membres bureau avec comptes utilisateurs (Annick AUDUREAU, Marie-Noëlle NIVEAU, Joëlle POIRIER, Pierre-Yves GARNIER), 4 membres comité directeur, 15 licenciés génériques (~25 au total), 3 groupes organisationnels (Bureau, Conseil d'Administration, Commission Vitafédé), et 4 réunions (3 Completed avec CRs + 1 Scheduled le 19 mai — réunion de démo live). Le seeder est idempotent : si l'association existe déjà, il recrée uniquement les réunions via refreshDemoMeetings() en préservant membres et licences.

0.5.1.1 — 2026-04-28

Ajouts

  • Responsables légaux dans les fiches enfants : les 60 enfants mineurs seedés (familles Cas1 et Cas2 du ClubAssoSeeder) ont désormais un responsable légal rattaché — père ou mère selon la parité, non-membre pour Cas2. Le tab "Responsables légaux" de PersonIdentityTab n'est plus vide en démo.
  • Exceptions de créneaux : le calendrier du ClubAssoSeeder inclut maintenant deux exceptions — une annulation passée (Judo Loisir lundi, il y a 3 semaines, travaux électriques) et un report futur (Judo Enfant mercredi → jeudi dans 2 semaines, salle modifiée). La feature de gestion des exceptions est visible dès le premier démarrage de la démo.
  • Diversité des statuts d'inscription : parmi les 56 adultes solo du ClubAssoSeeder, 3 inscriptions illustrent désormais des statuts distincts : PendingValidation (en attente de validation), Cancelled (annulée) et Draft (brouillon non soumis). Le cycle de vie complet d'une inscription est maintenant représenté.
  • Réunions enrichies : les trois seeders de démo (ClubAsso, DemoLigue56, AssoCultureSeeder) alignent leurs réunions sur le cycle complet v0.5 — statuts, participants, compte-rendus validés, actions assignées, next_meeting_at, et transcription Voxtral pour ClubAsso.

Corrections

  • Dates Carbon des exceptions de créneaux : next('Monday') remplacé par previous('Monday') pour garantir une date passée même quand aujourd'hui est un lundi. La date de report (mercredi → jeudi) utilise désormais une variable partagée pour éviter toute divergence si le seeder s'exécute en chevauchement de minuit.