diff --git a/app/api/jury.py b/app/api/jury.py
index 2800c77a99da18b0d4db3b2c0076c09191468aab..7de6cdef08fd42f240125b43eabc85804ecf86a1 100644
--- a/app/api/jury.py
+++ b/app/api/jury.py
@@ -5,9 +5,10 @@
 ##############################################################################
 
 """
-  ScoDoc 9 API : jury   WIP
+  ScoDoc 9 API : jury   WIP à compléter avec enregistrement décisions
 """
 
+from flask import g, url_for
 from flask_json import as_json
 from flask_login import login_required
 
@@ -24,6 +25,7 @@ from app.models import (
     Identite,
     ScolarAutorisationInscription,
     ScolarFormSemestreValidation,
+    ScolarNews,
 )
 from app.scodoc import sco_cache
 from app.scodoc.sco_permissions import Permission
@@ -47,6 +49,20 @@ def decisions_jury(formsemestre_id: int):
         raise ScoException("non implemente")
 
 
+def _news_delete_jury_etud(etud: Identite):
+    "génère news sur effacement décision"
+    # n'utilise pas g.scodoc_dept, pas toujours dispo en mode API
+    url = url_for(
+        "scolar.ficheEtud", scodoc_dept=etud.departement.acronym, etudid=etud.id
+    )
+    ScolarNews.add(
+        typ=ScolarNews.NEWS_JURY,
+        obj=etud.id,
+        text=f"""Suppression décision jury pour <a href="{url}">{etud.nomprenom}</a>""",
+        url=url,
+    )
+
+
 @bp.route(
     "/etudiant/<int:etudid>/jury/validation_ue/<int:validation_id>/delete",
     methods=["POST"],
@@ -94,6 +110,7 @@ def _validation_ue_delete(etudid: int, validation_id: int):
     db.session.delete(validation)
     sco_cache.invalidate_formsemestre_etud(etud)
     db.session.commit()
+    _news_delete_jury_etud(etud)
     return "ok"
 
 
@@ -121,6 +138,7 @@ def autorisation_inscription_delete(etudid: int, validation_id: int):
     db.session.delete(validation)
     sco_cache.invalidate_formsemestre_etud(etud)
     db.session.commit()
+    _news_delete_jury_etud(etud)
     return "ok"
 
 
@@ -148,6 +166,7 @@ def validation_rcue_delete(etudid: int, validation_id: int):
     db.session.delete(validation)
     sco_cache.invalidate_formsemestre_etud(etud)
     db.session.commit()
+    _news_delete_jury_etud(etud)
     return "ok"
 
 
@@ -175,4 +194,5 @@ def validation_annee_but_delete(etudid: int, validation_id: int):
     db.session.delete(validation)
     sco_cache.invalidate_formsemestre_etud(etud)
     db.session.commit()
+    _news_delete_jury_etud(etud)
     return "ok"
diff --git a/app/but/jury_but.py b/app/but/jury_but.py
index d9f8031a2f61d9bd2d725051bedb868f2b77cfee..1a5c1a4c662d11f41d542ed6b2a5dff146642974 100644
--- a/app/but/jury_but.py
+++ b/app/but/jury_but.py
@@ -459,10 +459,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
         """informations, for debugging purpose."""
         text = f"""<b>DecisionsProposeesAnnee</b>
         <ul>
-        <li>Etudiant: <a href="{url_for("scolar.ficheEtud", 
-            scodoc_dept=g.scodoc_dept, etudid=self.etud.id)
-        }">{self.etud.nomprenom}</a>
-        </li>
+        <li>Étudiant: {self.etud.html_link_fiche()}</li>
         """
         for formsemestre, title in (
             (self.formsemestre_impair, "formsemestre_impair"),
diff --git a/app/but/jury_but_validation_auto.py b/app/but/jury_but_validation_auto.py
index e698b5dd40d6768882340f5861ef0417baaea68f..a061b42f11bb3b797c26eddb6ad6c50b7bbee00f 100644
--- a/app/but/jury_but_validation_auto.py
+++ b/app/but/jury_but_validation_auto.py
@@ -6,11 +6,11 @@
 
 """Jury BUT: calcul des décisions de jury annuelles "automatiques"
 """
+from flask import g, url_for
 
 from app import db
 from app.but import jury_but
-from app.models.etudiants import Identite
-from app.models.formsemestre import FormSemestre
+from app.models import Identite, FormSemestre, ScolarNews
 from app.scodoc import sco_cache
 from app.scodoc.sco_exceptions import ScoValueError
 
@@ -39,4 +39,14 @@ def formsemestre_validation_auto_but(
             nb_etud_modif += deca.record_all(only_validantes=only_adm)
 
     db.session.commit()
+    ScolarNews.add(
+        typ=ScolarNews.NEWS_JURY,
+        obj=formsemestre.id,
+        text=f"""Calcul jury automatique du semestre {formsemestre.html_link_status()}""",
+        url=url_for(
+            "notes.formsemestre_status",
+            scodoc_dept=g.scodoc_dept,
+            formsemestre_id=formsemestre.id,
+        ),
+    )
     return nb_etud_modif
diff --git a/app/but/jury_but_view.py b/app/but/jury_but_view.py
index 87321684e2613b534e3436d64616c5999e907be4..275d93b1e3f6ee4197a31ba146a6b2bfe88d52cb 100644
--- a/app/but/jury_but_view.py
+++ b/app/but/jury_but_view.py
@@ -31,6 +31,7 @@ from app.models import (
     UniteEns,
     ScolarAutorisationInscription,
     ScolarFormSemestreValidation,
+    ScolarNews,
 )
 from app.models.config import ScoDocSiteConfig
 from app.scodoc import html_sco_header
@@ -369,6 +370,16 @@ def jury_but_semestriel(
                         flash(
                             f"autorisation de passage en S{formsemestre.semestre_id + 1} annulée"
                         )
+            ScolarNews.add(
+                typ=ScolarNews.NEWS_JURY,
+                obj=formsemestre.id,
+                text=f"""Saisie décision jury dans {formsemestre.html_link_status()}""",
+                url=url_for(
+                    "notes.formsemestre_status",
+                    scodoc_dept=g.scodoc_dept,
+                    formsemestre_id=formsemestre.id,
+                ),
+            )
         return flask.redirect(
             url_for(
                 "notes.formsemestre_validation_but",
diff --git a/app/models/events.py b/app/models/events.py
index 6555948d60b199193a177dcd18aeae83ae2b240e..d3e7709761262dc6db73f1465eec99862d3fed5b 100644
--- a/app/models/events.py
+++ b/app/models/events.py
@@ -54,14 +54,17 @@ class ScolarNews(db.Model):
     NEWS_APO = "APO"  # changements de codes APO
     NEWS_FORM = "FORM"  # modification formation (object=formation_id)
     NEWS_INSCR = "INSCR"  # inscription d'étudiants (object=None ou formsemestre_id)
+    NEWS_JURY = "JURY"  # saisie jury
     NEWS_MISC = "MISC"  # unused
     NEWS_NOTE = "NOTES"  # saisie note (object=moduleimpl_id)
     NEWS_SEM = "SEM"  # creation semestre (object=None)
+
     NEWS_MAP = {
         NEWS_ABS: "saisie absence",
         NEWS_APO: "modif. code Apogée",
         NEWS_FORM: "modification formation",
         NEWS_INSCR: "inscription d'étudiants",
+        NEWS_JURY: "saisie jury",
         NEWS_MISC: "opération",  # unused
         NEWS_NOTE: "saisie note",
         NEWS_SEM: "création semestre",
@@ -130,10 +133,10 @@ class ScolarNews(db.Model):
         return query.order_by(cls.date.desc()).limit(n).all()
 
     @classmethod
-    def add(cls, typ, obj=None, text="", url=None, max_frequency=0):
+    def add(cls, typ, obj=None, text="", url=None, max_frequency=600):
         """Enregistre une nouvelle
         Si max_frequency, ne génère pas 2 nouvelles "identiques"
-         à moins de max_frequency secondes d'intervalle.
+        à moins de max_frequency secondes d'intervalle (10 minutes par défaut).
         Deux nouvelles sont considérées comme "identiques" si elles ont
         même (obj, typ, user).
         La nouvelle enregistrée est aussi envoyée par mail.
@@ -153,7 +156,10 @@ class ScolarNews(db.Model):
             if last_news:
                 now = datetime.datetime.now(tz=last_news.date.tzinfo)
                 if (now - last_news.date) < datetime.timedelta(seconds=max_frequency):
-                    # on n'enregistre pas
+                    # pas de nouvel event, mais met à jour l'heure
+                    last_news.date = datetime.datetime.now()
+                    db.session.add(last_news)
+                    db.session.commit()
                     return
 
         news = ScolarNews(
diff --git a/app/scodoc/sco_edit_formation.py b/app/scodoc/sco_edit_formation.py
index 384ec0650c7876f567fc4b8d0bcb91b75ce5f79b..a3ce002a0ac76010b8be811127e0e041f40f60b8 100644
--- a/app/scodoc/sco_edit_formation.py
+++ b/app/scodoc/sco_edit_formation.py
@@ -132,6 +132,7 @@ def do_formation_delete(formation_id):
         typ=ScolarNews.NEWS_FORM,
         obj=formation_id,
         text=f"Suppression de la formation {acronyme}",
+        max_frequency=0,
     )
 
 
@@ -329,6 +330,7 @@ def do_formation_create(args: dict) -> Formation:
         typ=ScolarNews.NEWS_FORM,
         text=f"""Création de la formation {
             formation.titre} ({formation.acronyme}) version {formation.version}""",
+        max_frequency=0,
     )
     return formation
 
diff --git a/app/scodoc/sco_edit_matiere.py b/app/scodoc/sco_edit_matiere.py
index 312f01ec120419eb7dbf865829a32e2e99d23f4c..ef425b49382b65216c4b2c9a31819b1d765440e5 100644
--- a/app/scodoc/sco_edit_matiere.py
+++ b/app/scodoc/sco_edit_matiere.py
@@ -93,7 +93,6 @@ def do_matiere_create(args):
         typ=ScolarNews.NEWS_FORM,
         obj=ue["formation_id"],
         text=f"Modification de la formation {formation.acronyme}",
-        max_frequency=10 * 60,
     )
     formation.invalidate_cached_sems()
     return r
@@ -199,7 +198,6 @@ def do_matiere_delete(oid):
         typ=ScolarNews.NEWS_FORM,
         obj=ue["formation_id"],
         text=f"Modification de la formation {formation.acronyme}",
-        max_frequency=10 * 60,
     )
     formation.invalidate_cached_sems()
 
diff --git a/app/scodoc/sco_edit_module.py b/app/scodoc/sco_edit_module.py
index 4d963c6e490c2d02accb3fbf5d984778592b6127..139afa8412e166241e606d8d44922e690e96e908 100644
--- a/app/scodoc/sco_edit_module.py
+++ b/app/scodoc/sco_edit_module.py
@@ -114,7 +114,6 @@ def do_module_create(args) -> int:
         typ=ScolarNews.NEWS_FORM,
         obj=formation.id,
         text=f"Modification de la formation {formation.acronyme}",
-        max_frequency=10 * 60,
     )
     formation.invalidate_cached_sems()
     return module_id
@@ -186,7 +185,6 @@ def do_module_delete(oid):
         typ=ScolarNews.NEWS_FORM,
         obj=mod["formation_id"],
         text=f"Modification de la formation {formation.acronyme}",
-        max_frequency=10 * 60,
     )
     formation.invalidate_cached_sems()
 
diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py
index ba6cb918eeb2f3b045657438418e8b1fe9f9a7ef..fbe8e2be9611c664182b8f0dcf8d072444d39e06 100644
--- a/app/scodoc/sco_edit_ue.py
+++ b/app/scodoc/sco_edit_ue.py
@@ -145,7 +145,6 @@ def do_ue_create(args):
         typ=ScolarNews.NEWS_FORM,
         obj=args["formation_id"],
         text=f"Modification de la formation {formation.acronyme}",
-        max_frequency=10 * 60,
     )
     formation.invalidate_cached_sems()
     return ue_id
@@ -230,7 +229,6 @@ def do_ue_delete(ue: UniteEns, delete_validations=False, force=False):
         typ=ScolarNews.NEWS_FORM,
         obj=formation.id,
         text=f"Modification de la formation {formation.acronyme}",
-        max_frequency=10 * 60,
     )
     #
     if not force:
diff --git a/app/scodoc/sco_etud.py b/app/scodoc/sco_etud.py
index 7bbf12b5f251e8dfe3ca8b462e845bcbd7924d96..827363c89d8fcddd8428cefee9d92bfa9648decc 100644
--- a/app/scodoc/sco_etud.py
+++ b/app/scodoc/sco_etud.py
@@ -671,6 +671,7 @@ def create_etud(cnx, args: dict = None):
         typ=ScolarNews.NEWS_INSCR,
         text='Nouvel étudiant <a href="%(url)s">%(nomprenom)s</a>' % etud,
         url=etud["url"],
+        max_frequency=0,
     )
     return etud
 
diff --git a/app/scodoc/sco_formations.py b/app/scodoc/sco_formations.py
index 981908c971271da3f9daca56556f7e23e18f28ed..398ed7d47ee4d0f4c7e8b7a46dc731dd42cddd20 100644
--- a/app/scodoc/sco_formations.py
+++ b/app/scodoc/sco_formations.py
@@ -638,6 +638,7 @@ def formation_create_new_version(formation_id, redirect=True):
         typ=ScolarNews.NEWS_FORM,
         obj=new_id,
         text=f"Nouvelle version de la formation {formation.acronyme}",
+        max_frequency=0,
     )
     if redirect:
         flash("Nouvelle version !")
diff --git a/app/scodoc/sco_formsemestre.py b/app/scodoc/sco_formsemestre.py
index 3d46b1de78d26150af54972f68db4c8ab4ade5f3..bac3352a71898f4a97c2bfb176f34047c2452c4b 100644
--- a/app/scodoc/sco_formsemestre.py
+++ b/app/scodoc/sco_formsemestre.py
@@ -261,6 +261,7 @@ def do_formsemestre_create(args, silent=False):
             typ=ScolarNews.NEWS_SEM,
             text='Création du semestre <a href="%(url)s">%(titre)s</a>' % args,
             url=args["url"],
+            max_frequency=0,
         )
     return formsemestre_id
 
diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py
index 4961e8a21e40bf647b04d1f4394e4a0797c73d1a..4a94f0bde8ff9877d287ee681ff6df46e03473fd 100644
--- a/app/scodoc/sco_formsemestre_edit.py
+++ b/app/scodoc/sco_formsemestre_edit.py
@@ -1521,6 +1521,7 @@ def do_formsemestre_delete(formsemestre_id):
         typ=ScolarNews.NEWS_SEM,
         obj=formsemestre_id,
         text="Suppression du semestre %(titre)s" % sem,
+        max_frequency=0,
     )
 
 
diff --git a/app/scodoc/sco_formsemestre_validation.py b/app/scodoc/sco_formsemestre_validation.py
index 3a173f0373cf073c2a200cd9dbd7f4bf17aba1e2..5712d3eb6c7972395273df94a44a2e1badfd2446 100644
--- a/app/scodoc/sco_formsemestre_validation.py
+++ b/app/scodoc/sco_formsemestre_validation.py
@@ -39,7 +39,7 @@ from app import db, log
 
 from app.comp import res_sem
 from app.comp.res_compat import NotesTableCompat
-from app.models import Formation, FormSemestre, UniteEns
+from app.models import Formation, FormSemestre, UniteEns, ScolarNews
 from app.models.notes import etud_has_notes_attente
 from app.models.validations import (
     ScolarAutorisationInscription,
@@ -992,16 +992,26 @@ def do_formsemestre_validation_auto(formsemestre_id):
                     )
                     nb_valid += 1
     log(
-        "do_formsemestre_validation_auto: %d validations, %d conflicts"
-        % (nb_valid, len(conflicts))
+        f"do_formsemestre_validation_auto: {nb_valid} validations, {len(conflicts)} conflicts"
     )
-    H = [html_sco_header.sco_header(page_title="Saisie automatique")]
-    H.append(
-        """<h2>Saisie automatique des décisions du semestre %s</h2>
-    <p>Opération effectuée.</p>
-    <p>%d étudiants validés (sur %s)</p>"""
-        % (sem["titreannee"], nb_valid, len(etudids))
+    ScolarNews.add(
+        typ=ScolarNews.NEWS_JURY,
+        obj=formsemestre.id,
+        text=f"""Calcul jury automatique du semestre {formsemestre.html_link_status()
+                                                      } ({nb_valid} décisions)""",
+        url=url_for(
+            "notes.formsemestre_status",
+            scodoc_dept=g.scodoc_dept,
+            formsemestre_id=formsemestre.id,
+        ),
     )
+    H = [
+        f"""{html_sco_header.sco_header(page_title="Saisie automatique")}
+        <h2>Saisie automatique des décisions du semestre {formsemestre.titre_annee()}</h2>
+    <p>Opération effectuée.</p>
+    <p>{nb_valid} étudiants validés sur {len(etudids)}</p>
+    """
+    ]
     if conflicts:
         H.append(
             f"""<p><b>Attention:</b> {len(conflicts)} étudiants non modifiés 
diff --git a/app/scodoc/sco_import_etuds.py b/app/scodoc/sco_import_etuds.py
index 736d6021210b25c524cb153cb8f58639beacd3bb..e7eb8dceb3c445c3d15c1d1975bd7e5cc7449ae6 100644
--- a/app/scodoc/sco_import_etuds.py
+++ b/app/scodoc/sco_import_etuds.py
@@ -480,6 +480,7 @@ def scolars_import_excel_file(
         text="Inscription de %d étudiants"  # peuvent avoir ete inscrits a des semestres differents
         % len(created_etudids),
         obj=formsemestre_id,
+        max_frequency=0,
     )
 
     log("scolars_import_excel_file: completing transaction")
diff --git a/app/scodoc/sco_synchro_etuds.py b/app/scodoc/sco_synchro_etuds.py
index 6685909c4ba47d6f7ba0198222781bf5d2db8d87..764d889f4234bb7ad4d334bc80ce3102569053fe 100644
--- a/app/scodoc/sco_synchro_etuds.py
+++ b/app/scodoc/sco_synchro_etuds.py
@@ -704,7 +704,6 @@ def do_import_etuds_from_portal(sem, a_importer, etudsapo_ident):
         typ=ScolarNews.NEWS_INSCR,
         text=f"Import Apogée de {len(created_etudids)} étudiants en ",
         obj=sem["formsemestre_id"],
-        max_frequency=10 * 60,  # 10'
     )
 
 
diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css
index 0173a14e5ed3b6256f5ed14ef09d63ece2b88049..ca1b1f12907004167d1f78b0a2d8a22c235c1277 100644
--- a/app/static/css/scodoc.css
+++ b/app/static/css/scodoc.css
@@ -629,7 +629,7 @@ div.news {
   border-radius: 8px;
 }
 
-div.news a {
+div.news a, div.news a.stdlink {
   color: black;
   text-decoration: none;
 }
diff --git a/app/views/notes.py b/app/views/notes.py
index c51571941bebd3edc496eca1ac02f52c08e470d8..1ef706934a61784ea45bc9dd73bdad6c2c7f0069 100644
--- a/app/views/notes.py
+++ b/app/views/notes.py
@@ -2410,6 +2410,16 @@ def formsemestre_validation_but(
     if request.method == "POST":
         if not read_only:
             deca.record_form(request.form)
+            ScolarNews.add(
+                typ=ScolarNews.NEWS_JURY,
+                obj=formsemestre.id,
+                text=f"""Saisie décision jury dans {formsemestre.html_link_status()}""",
+                url=url_for(
+                    "notes.formsemestre_status",
+                    scodoc_dept=g.scodoc_dept,
+                    formsemestre_id=formsemestre.id,
+                ),
+            )
             flash("codes enregistrés")
         return flask.redirect(
             url_for(
@@ -3059,7 +3069,6 @@ def formsemestre_set_apo_etapes():
         ScolarNews.add(
             typ=ScolarNews.NEWS_APO,
             text=f"Modification code Apogée du semestre {formsemestre.titre_annee()})",
-            max_frequency=10 * 60,
         )
     return ("", 204)
 
@@ -3081,7 +3090,6 @@ def formsemestre_set_elt_annee_apo():
         ScolarNews.add(
             typ=ScolarNews.NEWS_APO,
             text=f"Modification code Apogée du semestre {formsemestre.titre_annee()})",
-            max_frequency=10 * 60,
         )
     return ("", 204)
 
@@ -3103,7 +3111,6 @@ def formsemestre_set_elt_sem_apo():
         ScolarNews.add(
             typ=ScolarNews.NEWS_APO,
             text=f"Modification code Apogée du semestre {formsemestre.titre_annee()})",
-            max_frequency=10 * 60,
         )
     return ("", 204)
 
@@ -3125,7 +3132,6 @@ def ue_set_apo():
         ScolarNews.add(
             typ=ScolarNews.NEWS_FORM,
             text=f"Modification code Apogée d'UE dans la formation {ue.formation.titre} ({ue.formation.acronyme})",
-            max_frequency=10 * 60,
         )
     return ("", 204)
 
@@ -3146,8 +3152,8 @@ def module_set_apo():
         db.session.commit()
         ScolarNews.add(
             typ=ScolarNews.NEWS_FORM,
-            text=f"Modification code Apogée d'UE dans la formation {mod.formation.titre} ({mod.formation.acronyme})",
-            max_frequency=10 * 60,
+            text=f"""Modification code Apogée d'UE dans la formation {
+                mod.formation.titre} ({mod.formation.acronyme})""",
         )
     return ("", 204)
 
diff --git a/sco_version.py b/sco_version.py
index 7be8d568b31038b828eb31304fb44e65e3e8a0a3..bd238565a60cd07ecb8b1665a51263bbfd90ed81 100644
--- a/sco_version.py
+++ b/sco_version.py
@@ -1,7 +1,7 @@
 # -*- mode: python -*-
 # -*- coding: utf-8 -*-
 
-SCOVERSION = "9.4.90"
+SCOVERSION = "9.4.91"
 
 SCONAME = "ScoDoc"