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 11 à 14 sur 14

0.5.1.0 — 2026-04-28

Ajouts

  • Transcription en temps réel (Voxtral) : pendant une réunion en direct, le bouton micro capture l'audio par chunks de 4 s et les envoie à Mistral Voxtral via un job en file d'attente. La transcription s'accumule dans le champ transcript de la réunion et est visible dans le compte-rendu final.
  • Provider de transcription configurable : config/ai.php expose default_for_transcription (valeur par défaut : mistral) pour faciliter le changement de provider sans toucher au code.
  • Transcription dans le compte-rendu : si une transcription est disponible, elle est incluse dans le compte-rendu généré (section dédiée, formatée en bloc citation pour éviter toute injection Markdown).
  • Robustesse micro : les chunks vides (micro muet, coupure réseau) sont filtrés avant envoi — aucune requête inutile vers l'API, pas de transcription parasite. Capture du segment EBML WebM garantie avant le filtre de taille.

Corrections

  • CSRF 419 sur transcribe-chunk : Inertia ne génère pas de balise <meta name="csrf-token"> — corrigé en lisant le cookie XSRF-TOKEN via l'en-tête X-XSRF-TOKEN (mécanisme natif Laravel/Sanctum).
  • Isolation tenant sur le job de transcription : la clause WHERE tenant_id = ? garantit qu'un job ne peut pas écrire dans la réunion d'un autre tenant même en cas de collision d'ID.
  • Stockage privé des chunks audio : forçage du disque local (privé) pour les fichiers audio temporaires — ils n'étaient pas exposés via URL publique dans le précédent comportement, mais cette garantie est maintenant explicite.
  • Nettoyage des fichiers audio orphelins : le fichier temporaire est désormais supprimé dans failed() en plus du finally de handle() — évite l'accumulation sur le FS Bucket en cas de SIGKILL du worker.
  • Throttle liveTranscript : le polling de transcription est limité à 30 req/min pour limiter la charge base de données.
  • Validation MIME des chunks : liste blanche stricte (audio/webm, audio/ogg, audio/wav, etc.) — les formats non reconnus reçoivent une 422.
  • Race condition post-arrêt enregistrement : les chunks reçus après l'appel à stopRecording() sont ignorés pour éviter les doubles uploads.
  • Accessibilité bouton micro : suppression de l'aria-label statique qui écrasait le texte dynamique visible (violation WCAG 2.5.3).

0.5.0.0 — 2026-04-23

Ajouts

  • Réunion en direct (Live) : nouvelle page de conduite de réunion en temps réel avec timer, navigation entre points de l'ordre du jour et affichage du temps écoulé. Chaque point peut être démarré, décidé et clôturé individuellement.
  • Actions de réunion : les animateurs peuvent créer des actions (tâches) sur chaque point de l'ordre du jour en séance, avec titre, responsable et date d'échéance.
  • Compte-rendu automatique : à la clôture d'une réunion, un compte-rendu Markdown est généré automatiquement à partir des décisions et actions enregistrées. La date de la prochaine réunion peut être saisie lors de la clôture.
  • Export PDF du compte-rendu : les CR validés sont exportables en PDF avec mise en forme professionnelle (logo, titre, présences, ordre du jour, décisions, actions).
  • Envoi email du compte-rendu : envoi idempotent du CR validé à tous les participants disposant d'une adresse email, avec protection contre les doublons d'envoi.
  • Recherche de décisions : nouvelle page de recherche full-text (GIN index PostgreSQL) dans les décisions de toutes les réunions clôturées.
  • Actions sur fiche membre : la fiche d'un membre affiche désormais les actions de réunion qui lui sont assignées, avec lien vers la réunion concernée.
  • Enrichissement de l'ordre du jour : chaque point de l'ordre du jour accepte une durée estimée (1–480 min) et un responsable utilisateur ; le formulaire de création/édition expose ces champs.

Modifications

  • Formulaire d'édition des réunions : l'ordre du jour est masqué et exclu de la soumission pour les réunions en cours (live) ou clôturées (completed), évitant les erreurs 422.
  • Statut live dans l'interface : les pages Index et Show affichent maintenant le statut live avec un badge warning ; le type TypeScript est mis à jour en conséquence.
  • Validation storeAction : le champ responsible_user_id est désormais validé et limité aux utilisateurs du tenant courant.
  • emailReport atomique : l'envoi est protégé contre les doublons par un UPDATE … WHERE NULL atomique plutôt qu'une lecture puis écriture.
  • Email CR : le contenu Markdown du compte-rendu est converti en HTML avant envoi, les destinataires voient le texte formaté plutôt que la syntaxe brute.

Corrections

  • Watcher Vue (AgendaItemPanel) : [...undefined] corrigé en [...(item.actions ?? [])] lorsque la réponse API ne retourne pas la relation actions.
  • Réponse updateAgendaItem : charge désormais actions.responsible avant de sérialiser, évitant les erreurs côté client.
  • Clé de pagination v-for dans Decisions.vue rendue unique (label + url).

0.4.7.0 - 2026-04-22

Corrections

  • Sécurité multi-tenant : MeetingReport manquait le trait BelongsToTenant — les comptes-rendus n'étaient pas filtrés par tenant. Migration de backfill ajoutée (tenant_id sur meeting_reports).
  • Injection cross-réunion : il était possible d'envoyer l'ID d'un participant d'une autre réunion dans updateAttendance. La validation Rule::exists scopée sur meeting_id bloque désormais ces requêtes au niveau FormRequest.
  • N+1 sur la présence : les mises à jour de présence faisaient une requête SQL par participant. Remplacé par batchUpdateAttendance() qui groupe les UPDATE par statut.
  • Dégradation du statut de rapport : fermer une réunion avec des notes écrasait silencieusement un rapport Validated en Draft via updateOrCreate. Remplacé par un create/update explicite qui préserve le statut existant.
  • Double validation : il était possible de valider un rapport déjà validé. Garde abort_unless(Draft) ajoutée.
  • Contenu vide validé : un rapport sans contenu (ou contenu en espaces) pouvait être validé. Garde abort_if(blank()) ajoutée.
  • Annulation impossible : tenter d'annuler une réunion déjà terminée ou annulée renvoyait une erreur non gérée. Retourne maintenant 422.
  • Réactivité Vue : le contenu du rapport ne se synchronisait pas après une navigation Inertia. Watch ajouté sur props.meeting.report?.content.

0.2.1.0 - 2026-04-07

Ajouts

  • Système de design Cohez.io — identité visuelle définie et codée : polices Fraunces (titres) + Geist (interface) + Geist Mono (données financières), chargées via Bunny Fonts (GDPR-compliant). Palette de couleurs basée sur le vert sauge (#2D6A4F) comme couleur brand, fond crème #FAF9F7, neutrals chauds — différenciant dans la catégorie face au bleu corporate omniprésent (AssoConnect, HelloAsso).
  • Composant EmptyState (@/components/ui/empty-state) — état vide réutilisable : icône Lucide + titre + description + slot pour CTA optionnel. Appliqué sur les listes de membres, groupes, réunions.
  • Composant ConfirmDialog (@/components/ui/confirm-dialog) — dialogue de confirmation avant toute action destructive. Remplace entièrement les confirm() natifs (qui bloquent les events browser). Utilisé pour la désactivation/suppression de membres et groupes.
  • FlashToast (@/components/layout/FlashToast) — notification toast bottom-right consommant automatiquement flash.success et flash.error depuis les props Inertia partagées. Intégré dans AppSidebarLayout.
  • Bannière alerte impayés sur le tableau de bord — si des inscriptions non payées existent, une bannière rouge s'affiche en haut de page avec un lien direct vers la liste filtrée.
  • DESIGN.md — documentation complète du design system : couleurs avec rationale, typographie, espacement, border radius, motion, composants, patterns UI, responsive, accessibilité et journal de décisions.

Modifications

  • Dashboard — agenda de la semaine en empty state explicite quand aucune réunion n'est planifiée ; bannière impayés avec filtre URL correct.
  • Pages membres et groupes — états vides cohérents avec le composant EmptyState au lieu de textes inline.
  • Wizard d'inscription — garde contre 0 campagnes disponibles avec empty state explicite ; correction de l'affichage du récapitulatif sur mobile.

Corrections

  • Suppression du </div> en trop dans le wizard d'inscription (registrations/Create.vue).
  • Le lien "impayés" du dashboard utilisait un format de query params incorrect pour Wayfinder ({ status: 'unpaid' } → { query: { status: 'unpaid' } }).
  • FlashToast : ajout du onUnmounted pour nettoyer le timer, ajout de break-words sur le message pour éviter l'overflow sur les messages longs.