Journal des modifications
Les évolutions de Cohez.io, de la plus récente à la plus ancienne.
174 versions publiées.
Versions 51 à 60 sur 174
0.22.0.3 — 2026-07-29
Ajouts
- Couche port/domaine du moteur d'adhésions (aucun changement visible pour les utilisateurs) : port
MembershipRepositoryInterface+ adaptateur Eloquent, garde de domaineMembershipOverlapGuard(7 formes de recouvrement, cas jointif accepté), entitéMembershipRecord. La garde applique en PHP l'invariant que seule la contrainte PostgreSQLmemberships_no_overlaptenait jusqu'ici — donc jamais exercé en CI, où SQLite ne pose qu'un index unique partiel. La couche n'a aucun appelant : elle prépare la bascule en lecture (PR2) sans toucher au comportement actuel. Séquence d'écriture à respecter et dette assumée : Moteur de périodes d'adhésion.
Corrections
MembershipPeriodacceptait des périodes que PostgreSQL refuse. Deux divergences prouvées contre un vrai PostgreSQL puis fermées : (1) les bornes sont normalisées àstartOfDay()avant validation, carstart_date/end_datesont des colonnesdate— une composante horaire faisait diverger le verdict de chevauchement du VO et celui dudaterange; (2) une période inversée (start > end) est désormais rejetée par le VO, PostgreSQL la refusant avec le SQLSTATE22000et non23P01.
Documentation
- Nouveau document d'architecture : Global scope tenant vs filtre
tenant_idexplicite — à lire avant d'écrire un repository, un job ou une commande qui passe untenant_iden argument. Le global scopeBelongsToTenants'ajoute au filtre explicite au lieu de le remplacer, et ne s'applique pas aux INSERT : contexte divergent = lectures vides + écritures qui partent quand même, sans le moindre signal.
0.22.0.2 — 2026-07-28
Modifications
- Le mail d'invitation tenant (
TenantInvitationMail) rejoint le châssis de marque partagé : en-tête au nom du club, bouton d'action (<x-emails.button>, désormais extrait en composant réutilisable), bloc contact et pied « Envoyé à » — au lieu de l'ancien gabarit markdown générique. La ligne d'objet nomme directement l'association (« Bienvenue chez {tenant} ») et une version texte accompagne le HTML.
Corrections
- Le pied de page des e-mails sur châssis partagé portait une coquille (« Cohéz.io » avec accent) : harmonisé en « Cohez.io », l'orthographe correcte de la marque, sur tous les gabarits concernés (et rétroactivement dans les entrées de changelog déjà publiées qui la mentionnaient).
- Le mail d'invitation affichait littéralement l'ancien nom de code du projet au lieu du nom d'application configuré (
APP_NAME). - La date de validité du lien d'invitation pouvait afficher un nombre de jours flottant ou négatif (calcul
diffInDayssensible à l'heure d'envoi) ; elle affiche désormais une date fixe (d/m/Y). - Le nom du club dans le mail d'invitation pouvait apparaître doublement échappé (ex.
&#039;au lieu de') pour les associations dont le nom contient une apostrophe ou une esperluette.
0.22.0.1 — 2026-07-28
Corrections
- Upload de document tenant (Filament) crashait en 500 sur défaillance transitoire du stockage temporaire Livewire : la validation du fichier interrogeait le disk FS Bucket via Flysystem, dont une erreur
UnableToRetrieveMetadataremontait brute en 500 au lieu d'un message clair. Le comportement rejoint désormais celui de Livewire pour une session expirée : réponse 419, l'admin est invité à réessayer l'upload.
0.22.0.0 — 2026-07-27
Ajouts
- Export Excel des inscrits d'un cours : depuis la fiche d'un cours, export au format Excel (.xlsx) ou CSV des membres inscrits — nom, prénom, date de naissance, âge, téléphone, email, et jusqu'à 2 responsables légaux (nom, lien, téléphone, email) par membre mineur.
Modifications
- Format d'export enrichi : l'export CSV du cours passe du format minimal (id, nom, statut) à un export complet orienté trésorier/coach, avec délimiteur
;(convention Excel FR) et protection contre l'injection de formule sur tous les champs texte.
0.21.0.0 — 2026-07-26
Ajouts
- Alerte dashboard « campagnes bientôt clôturées » : le tableau de bord affiche désormais les campagnes d'inscription ouvertes dont la clôture programmée arrive dans les 7 jours, pour éviter de découvrir une fermeture automatique après coup.
- Page de clôture dédiée pour les inscriptions publiques (
/register/{token}/closed) : quand une campagne se ferme ou qu'un lien d'inscription expire, l'adhérent est redirigé vers une page qui explique clairement pourquoi, au lieu d'un message d'erreur générique.
Modifications
- Message d'erreur convivial à la clôture d'une campagne : le motif de fermeture (campagne close vs lien expiré) est désormais dérivé côté serveur (
CampaignPublicToken::closedReason()) plutôt que déclaré par le client, ce qui empêche un motif erroné ou falsifié d'être affiché. En cas de cumul des deux causes, le message priorise le lien expiré. - L'endpoint d'estimation tarifaire (
/register/{token}/estimate) répond désormais systématiquement en JSON 410 quand la campagne se ferme en cours de saisie, au lieu de rediriger vers une page HTML.
0.20.2.0 — 2026-07-23
Ajouts
- Pull backup prod Clever Cloud + anonymisation automatique de la base de dev :
scripts/pull-prod-backup.shtélécharge le dernier backup Postgres Clever Cloud de la prod, le restaure dans le conteneur Docker local, puis anonymise automatiquement toutes les données à caractère personnel via la nouvelle commandedb:anonymize— jamais d'étape manuelle séparée, jamais de vraie donnée personnelle qui atterrit en dev même transitoirement. Scramble déterministe (Faker seedé par ligne, idempotent) des colonnes structurées (persons,users,payeurs,partner_contacts,meeting_participants,invitation_tracking,registration_relance_emails,legal_guardians,meeting_actions,meetings), vidage du texte libre (transcriptions, notes, comptes-rendus) vers un placeholder générique, troncature des tables éphémères (sessions,password_reset_tokens). Garde-fou dur :db:anonymizerefuse de s'exécuter en environnementproduction, sans option de contournement. L'anonymisation est garantie même en cas d'échec partiel de la restauration (déclenchée par untrapsur la sortie du script, pas en séquence normale) ; un mode--dry-runpermet de vérifier le backup sélectionné sans rien télécharger ni exécuter. L'image Postgres locale (docker/postgres/Dockerfile) embarque désormaispostgis/pgvector, requis par le dump prod Clever Cloud (addon avec ces extensions activées par défaut) — sans quoipg_restoreéchouait avant même d'atteindre l'anonymisation.db:anonymizebascule aussi le mot de passe de tous lesuserssur"password"(hash bcrypt), pour permettre la connexion en local après restauration sans avoir accès au mot de passe prod original.admin_users(comptes internes Code Ethic nécessaires à l'administration de la plateforme) reste volontairement hors du périmètre d'anonymisation.
Corrections
- Emails scramblés par
db:anonymizepouvaient entrer en collision :Faker::safeEmail()tire d'un espace de valeurs fini malgré le seed déterministe par ligne, risquant de violerunique(tenant_id, email)sur un backup prod de taille réelle. L'email généré est désormais suffixé par un hash de l'id de ligne (clé primaire, garantie unique par table).
0.20.1.2 — 2026-07-23
Corrections
- Correctifs mineurs issus de la revue automatique
claude[bot]sur PR #238 : suppression d'un refetch inutile avantdispatchCloseIfNeeded(double requête superflue), typage précis du paramètreextradeCampaignTransitionGuard(retrait de l'annotation@phpstan-ignoredevenue inutile), couverture de test du comportementwhereNulldetryTransition()(dateNULLen base), couverture de test du rejet en race condition du guard.
0.20.1.1 — 2026-07-23
Corrections
CampaignController::open()/closeCampaign()bypassaientCampaignTransitionGuard: les actions manuelles d'ouverture/clôture faisaient unupdate()direct sur le modèle au lieu de passer par le guard atomique anti-TOCTOU, contredisant la description de la feature d'ouverture/fermeture automatique. Le guard accepte désormais un paramètreextra(colonnes additionnelles écrites dans la même requête atomique :opens_at/closes_at/updated_by) etdateColumn/expectedDatedeviennent optionnels, permettant au contrôleur de router ses transitions manuelles dessus sans risque de concurrence avec les jobs différés.
0.20.1.0 — 2026-07-22
Ajouts
- Ouverture/fermeture automatique des campagnes aux dates programmées : une campagne configurée avec
opens_at/closes_atrestait figée dans son statut tant qu'un admin ne cliquait pas manuellement sur « Ouvrir » ou « Clôturer » — elle pouvait resterDraftle jour J faute d'intervention, ouOpenbien après sa clôture prévue. Les transitionsDraft → OpenetOpen → Closeds'exécutent désormais automatiquement via des jobs différés (OpenCampaignJob/CloseCampaignJob), protégés par un guard atomique anti-TOCTOU (CampaignTransitionGuard::tryTransition, une seule requêteUPDATE ... WHERE status = ...fait toute la protection contre les exécutions concurrentes). Un filet de sécurité horaire (campaigns:sync-status --safety-net) rattrape toute transition manquée (job perdu, queue non consommée) avec jusqu'à 1h de retard. Voir Docs/Features/Campaign-Auto-Open-Close.md. Action manuelle requise avant déploiement : reconfigurerCC_WORKER_COMMAND_0sur Clever Cloud pour consommer la queuecampaigns.
0.20.0.4 — 2026-07-21
Ajouts
- 2FA (TOTP) obligatoire sur le panel admin Filament (
isRequired: true,App\Filament\Auth\AppAuthentication) : aucunAdminUserne peut plus accéder au panel sans enrôlement (QR code + code de confirmation), enrôlement forcé au premier login puis challenge TOTP/code de secours ensuite. Corrige au passage un bug d'affichage du QR code (double encodage en data URI, filamentphp/filament#16678).