diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ccdfc90c12d139e3d990021c89110437fc44b34..3a251c332ebb26bfd8c8d839d1ecef900bcf02d6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,12 @@
 Journal des modifications
 =========================
 
+6.0.4
+-----
+- [FIX] Recherche de rapports d'Activité/CSI/Mi-parcours : les filtres Établissement/ED/UR géraient mal la subsitution de structures.
+- Changement de la page de couverture pour tenir compte de la co-accréditation
+- Module Soutenance : Possibilité pour les structures de révoquer leur validation (avec modal de confirmation)
+
 6.0.3
 -----
 - [FIX] Signature de méthode setObject() modifiée en PHP8 dans Doctrine\Laminas\Hydrator\Strategy\AbstractCollectionStrategy.
diff --git a/data/SQL/profil.sql b/data/SQL/profil.sql
deleted file mode 100755
index d3d5bfaccfb1042d0e6c89d47affaa5e4a35ff9c..0000000000000000000000000000000000000000
--- a/data/SQL/profil.sql
+++ /dev/null
@@ -1,58 +0,0 @@
-
-rename ROLE_MODELE to PROFIL;
-rename ROLE_PRIVILEGE_MODELE to PROFIL_PRIVILEGE;
-
-alter table PROFIL add description varchar2(1024);
-
-create sequence PROFIL_ID_SEQ;
-
---
--- Avance d'une sequence.
---
-declare
-  maxid integer;
-  seqnextval integer;
-begin
-  select max(PROFIL.id) into maxid from PROFIL;
-  LOOP
-    select PROFIL_ID_SEQ.nextval into seqnextval from dual;
-    EXIT WHEN seqnextval >= maxid;
-  END LOOP;
-end;
-
-create unique index PROFIL_ROLE_ID_uindex on PROFIL (ROLE_ID);
-
-truncate table PROFIL_PRIVILEGE;
-
-alter table PROFIL modify STructure_type null;
-
-alter table PROFIL_PRIVILEGE drop constraint ROLE_PRIV_MOD_PK;
-alter table PROFIL_PRIVILEGE drop column ROLE_CODE;
-alter table PROFIL_PRIVILEGE add PROFIL_ID number;
-alter table PROFIL_PRIVILEGE add constraint PROFIL_PRIVILEGE_PROFIL_ID_fk foreign key (PROFIL_ID) references PROFIL;
-alter table PROFIL_PRIVILEGE add constraint PROFIL_PRIVILEGE_PK primary key (PROFIL_ID, PRIVILEGE_ID);
-
-create table PROFIL_TO_ROLE (
-                              PROFIL_ID integer not null constraint PROFIL_TO_ROLE_PROFIL_ID_fk references PROFIL,
-                              ROLE_ID integer not null constraint PROFIL_TO_ROLE_ROLE_ID_fk references ROLE,
-                              constraint PROFIL_TO_ROLE_pk primary key (PROFIL_ID, ROLE_ID)
-);
-
--- INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (1, 'Unité de recherche', 'UR', 3, null);
--- INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (2, 'École doctorale', 'ED', 2, null);
--- INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (3, 'Administrateur', 'ADMIN', 1, 'Administrateur d''établissement');
--- INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (4, 'Maison du doctorat', 'BDD', 1, null);
--- INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (5, 'Bibliothèque universitaire', 'BU', 1, null);
-INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (6, 'Administrateur technique', 'ADMIN_TECH', null, null);
-INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (7, 'Doctorant', 'DOCTORANT', null, null);
-INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (8, 'Observateur', 'OBSERV', null, null);
-INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (9, 'Directeur', 'D', null, null);
-INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (10, 'Co-directeur', 'K', null, null);
-INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (11, 'Rapporteur', 'R', null, null);
-INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (12, 'Membre', 'M', null, null);
-INSERT INTO PROFIL (ID, LIBELLE, ROLE_ID, STRUCTURE_TYPE, DESCRIPTION) VALUES (61, 'Doctorant sans dépôt', 'NODEPOT', null, 'Rôle de doctorant temporaire');
-
-INSERT INTO PRIVILEGE (ID, CATEGORIE_ID, CODE, LIBELLE, ORDRE) VALUES (36, 19, 'consultation-toutes-structures', 'Consultation de toutes les substitutions', 200);
-INSERT INTO PRIVILEGE (ID, CATEGORIE_ID, CODE, LIBELLE, ORDRE) VALUES (37, 19, 'consultation-sa-structure', 'Consultation de la substitution de sa structure', 300);
-INSERT INTO PRIVILEGE (ID, CATEGORIE_ID, CODE, LIBELLE, ORDRE) VALUES (38, 19, 'modification-toutes-structures', 'Modification de toutes les substitutions ', 400);
-INSERT INTO PRIVILEGE (ID, CATEGORIE_ID, CODE, LIBELLE, ORDRE) VALUES (39, 19, 'modification-sa-structure', 'Modification de la substitution de sa structure', 500);
diff --git a/doc/release-notes/v6.0.4.md b/doc/release-notes/v6.0.4.md
new file mode 100644
index 0000000000000000000000000000000000000000..1368647c6624f664df0b96726d3f3ff9a3deedb7
--- /dev/null
+++ b/doc/release-notes/v6.0.4.md
@@ -0,0 +1,69 @@
+# Version 6.0.4
+
+## 1. Sur le serveur d'application
+
+*Rappel : depuis la version 6.0.0, la version de PHP requise est la 8.0.*
+
+- Placez-vous dans le répertoire de l'application puis lancez la commande suivante
+  pour installer la nouvelle version :
+
+```bash
+git fetch --tags && git checkout --force 6.0.4 && bash ./install.sh
+```
+
+- Rechargez le moteur PHP, exemple :
+
+```bash
+systemctl reload php8.0-fpm
+```
+
+## 2. Dans la base de données
+
+```postgresql
+-- Ajout du privilège pour revoquer
+INSERT INTO privilege (categorie_id, code, libelle, ordre)
+WITH d(code, lib, ordre) AS (
+    SELECT 'proposition-revoquer-structure', 'Révoquer la validation (structure) de la proposition', 34
+)
+SELECT cp.id, d.code, d.lib, d.ordre
+FROM d
+JOIN categorie_privilege cp ON cp.CODE = 'soutenance';
+
+--Ajout au profil
+INSERT INTO PROFIL_PRIVILEGE (PRIVILEGE_ID, PROFIL_ID)
+with data(categ, priv) as (
+  select 'soutenance'::text, 'proposition-revoquer-structure'::text
+)
+select p.id as PRIVILEGE_ID, profil.id as PROFIL_ID
+from data
+       join PROFIL on profil.ROLE_ID in ('RESP_ED', 'RESP_UR', 'BDD')
+       join CATEGORIE_PRIVILEGE cp on cp.CODE = data.categ
+       join PRIVILEGE p on p.CATEGORIE_ID = cp.id and p.code = data.priv
+where not exists (
+  select * from PROFIL_PRIVILEGE where PRIVILEGE_ID = p.id and PROFIL_ID = profil.id
+);
+
+INSERT INTO PROFIL_PRIVILEGE (PRIVILEGE_ID, PROFIL_ID)
+with data(categ, priv) as (
+  select 'missionenseignement'::text, 'missionenseignement_modifier'::text
+)
+select p.id as PRIVILEGE_ID, profil.id as PROFIL_ID
+from data
+       join PROFIL on profil.ROLE_ID in ('ADMIN_TECH', 'GEST_FORMATION', 'BDD', 'ADMIN')
+       join CATEGORIE_PRIVILEGE cp on cp.CODE = data.categ
+       join PRIVILEGE p on p.CATEGORIE_ID = cp.id and p.code = data.priv
+where not exists (
+  select * from PROFIL_PRIVILEGE where PRIVILEGE_ID = p.id and PROFIL_ID = profil.id
+);
+
+insert into ROLE_PRIVILEGE (ROLE_ID, PRIVILEGE_ID)
+select p2r.ROLE_ID, pp.PRIVILEGE_ID
+from PROFIL_TO_ROLE p2r
+       join profil pr on pr.id = p2r.PROFIL_ID
+       join PROFIL_PRIVILEGE pp on pp.PROFIL_ID = pr.id
+where not exists (
+  select * from role_privilege where role_id = p2r.role_id and privilege_id = pp.privilege_id
+);
+
+
+```
\ No newline at end of file
diff --git a/module/Application/src/Application/Service/Rapport/RapportSearchService.php b/module/Application/src/Application/Service/Rapport/RapportSearchService.php
index a70cf1088df5b03727c23d1670ed2d270bf6c120..8b4597d05a239880ce536a775446121b7d763d50 100644
--- a/module/Application/src/Application/Service/Rapport/RapportSearchService.php
+++ b/module/Application/src/Application/Service/Rapport/RapportSearchService.php
@@ -83,7 +83,7 @@ class RapportSearchService extends SearchService
         $etablissementInscrFilter = $this->getEtablissementTheseSearchFilter()
             ->setQueryBuilderApplier(function (SelectSearchFilter $filter, DefaultQueryBuilder $qb) {
                 $qb
-                    ->andWhere('etab.sourceCode = :sourceCodeEtab OR etab_structureSubstituante.sourceCode = :sourceCodeEtab')
+                    ->andWhere('etab.sourceCode = :sourceCodeEtab OR etab_substituant.sourceCode = :sourceCodeEtab')
                     ->setParameter('sourceCodeEtab', $filter->getValue());
             })
             ->setDataProvider(function() {
@@ -96,7 +96,7 @@ class RapportSearchService extends SearchService
         $uniteRechercheFilter = $this->getUniteRechercheSearchFilter()
             ->setQueryBuilderApplier(function (SelectSearchFilter $filter, DefaultQueryBuilder $qb) {
                 $qb
-                    ->andWhere('ur.sourceCode = :sourceCodeUR OR ur_structureSubstituante.sourceCode = :sourceCodeUR')
+                    ->andWhere('ur.sourceCode = :sourceCodeUR OR ur_substituant.sourceCode = :sourceCodeUR')
                     ->setParameter('sourceCodeUR', $filter->getValue());
             })
             ->setDataProvider(function() {
@@ -105,7 +105,7 @@ class RapportSearchService extends SearchService
         $ecoleDoctoraleFilter = $this->getEcoleDoctoraleSearchFilter()
             ->setQueryBuilderApplier(function (SelectSearchFilter $filter, DefaultQueryBuilder $qb) {
                 $qb
-                    ->andWhere('ed.sourceCode = :sourceCodeED OR ed_structureSubstituante.sourceCode = :sourceCodeED')
+                    ->andWhere('ed.sourceCode = :sourceCodeED OR ed_substituant.sourceCode = :sourceCodeED')
                     ->setParameter('sourceCodeED', $filter->getValue());
             })
             ->setDataProvider(function() {
@@ -318,7 +318,10 @@ class RapportSearchService extends SearchService
             ->leftJoin('ur.structure', 'ur_structure')->addSelect('ur_structure')
             ->leftJoinStructureSubstituante('etab_structure', 'etab_structureSubstituante')
             ->leftJoinStructureSubstituante('ed_structure', 'ed_structureSubstituante')
-            ->leftJoinStructureSubstituante('ur_structure', 'ur_structureSubstituante');
+            ->leftJoinStructureSubstituante('ur_structure', 'ur_structureSubstituante')
+            ->leftJoin('etab_structureSubstituante.etablissement', 'etab_substituant')->addSelect('etab_substituant')
+            ->leftJoin('ed_structureSubstituante.ecoleDoctorale', 'ed_substituant')->addSelect('ed_substituant')
+            ->leftJoin('ur_structureSubstituante.uniteRecherche', 'ur_substituant')->addSelect('ur_substituant');
 
         if ($this->typeRapport !== null) {
             $qb->andWhere('tr = :type')->setParameter('type', $this->typeRapport);
diff --git a/module/Application/view/application/utilisateur/lier-individu.phtml b/module/Application/view/application/utilisateur/lier-individu.phtml
index 4d78f8aa4e9c198a8ae59980a4ac66c8d314c09b..340d22aea66286e1f2c4abfb46a29e0b2838caa9 100644
--- a/module/Application/view/application/utilisateur/lier-individu.phtml
+++ b/module/Application/view/application/utilisateur/lier-individu.phtml
@@ -16,7 +16,7 @@ use Application\Entity\Db\Utilisateur;
 use UnicaenApp\Form\Element\SearchAndSelect;
 ?>
 
-<?php if ($individu !== null and $utilisateur !== null and $utilisateur->getIndividu() === $individu) : ?>
+<?php if (isset($individu) and $utilisateur !== null and $utilisateur->getIndividu() === $individu) : ?>
 
     <div class="alert alert-success">
         Le compte utilisateur &laquo; <?php echo $utilisateur->getDisplayName(); ?> &raquo;
@@ -51,7 +51,7 @@ use UnicaenApp\Form\Element\SearchAndSelect;
         </div>
     </div>
 
-    <?php if ($individu)  : ?>
+    <?php if (isset($individu))  : ?>
         <div class="box card">
             <div class="card-header bg-dark text-white">
                 <h2 class="first">
@@ -168,7 +168,7 @@ use UnicaenApp\Form\Element\SearchAndSelect;
 
         <?php echo $this->ajouterIndividuChildView ?>
 
-    <?php elseif ($individu === null) : ?>
+    <?php elseif (!isset($individu)) : ?>
 
         <form method="post"
               action="<?php echo $this->url('utilisateur/lier-individu', ['utilisateur' => $utilisateur->getId()], [], true); ?>">
diff --git a/module/Depot/view/depot/depot/page-de-couverture/pagedecouverture.phtml b/module/Depot/view/depot/depot/page-de-couverture/pagedecouverture.phtml
index 0dfe1a74485b3a51b8b7b3d6a35c87946fdc9932..abd0ea9e74327e3ce43509415aa5360d8d529db8 100644
--- a/module/Depot/view/depot/depot/page-de-couverture/pagedecouverture.phtml
+++ b/module/Depot/view/depot/depot/page-de-couverture/pagedecouverture.phtml
@@ -18,16 +18,49 @@ use Application\View\Renderer\PhpRenderer;
  */
 ?>
 
-<!-- SECTION DU LOGO DE LA COMUE -------------------------------------------------------------------------------------->
-<div style="text-align: center; margin-bottom: 30px;">
+<!-- HEADER NORMAND --------------------------------------------------------------------------------------------------->
+<!--
+    A GAUCHE  >>> LE LOGO DE LA COMUE
+    A DROITE  >>> LE LOGO DE L'ETABLISSEMENT D'INSCRIPTION
+-->
+
+<style>
+    .logo-header {
+        border: 2px hotpink solid;
+        max-height: 5cm;
+        max-width: 5cm;
+    }
+</style>
+
+<?php if ($informations->getLogoCOMUE() !== null): ?>
+    <table style="border:none;" class="logos">
+        <tr>
+            <td>
+                <?php if ($informations->getLogoCOMUE() !== null): ?>
+                    <img src="<?php echo $informations->getLogoCOMUE() ?>" alt="Logo de la COMUE" class="logo-header"/>
+                <?php else: ?>
+                    <span style='background-color:red;'> Logo de la COMUE. </span>
+                <?php endif; ?>
+            </td>
+            <td>
+                <?php if ($informations->getLogoEtablissement() !== null): ?>
+                    <img src="<?php echo $informations->getLogoEtablissement() ?>" alt="Logo de l'établissement d'inscription" class="logo-header"/>
+                <?php else: ?>
+                    <span style='background-color:red;'> Logo de l'établissement non renseigné. </span>
+                <?php endif; ?>
+            </td>
+        </tr>
+    </table>
+<?php else : ?>
     <div class='logo-comue'>
-        <?php if ($informations->getLogoCOMUE() !== null): ?>
-            <img src="<?php echo $informations->getLogoCOMUE() ?>"/>
+        <?php if ($informations->getLogoEtablissement() !== null): ?>
+            <img src="<?php echo $informations->getLogoEtablissement() ?>" alt="Logo de l'établissement d'inscription"/>
         <?php else: ?>
-            <span style='background-color:red;'> COMUE ou logo de la COMUE non renseigné. </span>
+            <span style='background-color:red;'> Logo de l'établissement non renseigné. </span>
         <?php endif; ?>
     </div>
-</div>
+<?php endif; ?>
+
 
 <!-- ENTETE DE LA PAGE DE COUVERTURE ---------------------------------------------------------------------------------->
 <div class='bandeau-these'>
@@ -139,13 +172,6 @@ use Application\View\Renderer\PhpRenderer;
 <div class="logos">
 <table style="border:none;" class="logos">
     <tr>
-        <td>
-            <?php if ($informations->getLogoEtablissement()): ?>
-                <img class="logo_small" src="<?php echo $informations->getLogoEtablissement() ?>"/>
-            <?php else: ?>
-                <span style='background-color:red;'> Établissement d'inscription ou logo d'établissement non renseigné. </span>
-            <?php endif; ?>
-        </td>
         <?php if ($informations->isAssocie()): ?>
             <td>
                 <?php if ($informations->getLogoAssocie()): ?>
diff --git a/module/Individu/view/individu/individu/partial/dl.phtml b/module/Individu/view/individu/individu/partial/dl.phtml
index 58fe36248d5c44fabed45016bc7bea75bef6dfa1..0242d7da038e4e183b2bde8bdd60bbf45c50ca2d 100644
--- a/module/Individu/view/individu/individu/partial/dl.phtml
+++ b/module/Individu/view/individu/individu/partial/dl.phtml
@@ -3,6 +3,8 @@
  * @var \Individu\Entity\Db\Individu $individu
  * @var bool $verbose
  */
+
+if (!isset($verbose)) $verbose = false;
 ?>
 <dl class="row">
     <?php if ($individu->getCivilite()): ?>
diff --git a/module/RapportActivite/src/RapportActivite/Service/Search/RapportActiviteSearchService.php b/module/RapportActivite/src/RapportActivite/Service/Search/RapportActiviteSearchService.php
index e7d68ff540d0775903793caa425a4530a39d003f..0ef95347407bf3b2503e25e1c19d74158bcd0ed3 100644
--- a/module/RapportActivite/src/RapportActivite/Service/Search/RapportActiviteSearchService.php
+++ b/module/RapportActivite/src/RapportActivite/Service/Search/RapportActiviteSearchService.php
@@ -76,19 +76,19 @@ class RapportActiviteSearchService extends SearchService
         $etablissementInscrFilter = $this->getEtablissementTheseSearchFilter()
             ->setQueryBuilderApplier(function (SelectSearchFilter $filter, DefaultQueryBuilder $qb) {
                 $qb
-                    ->andWhere('etab.sourceCode = :sourceCodeEtab OR etab_structureSubstituante.sourceCode = :sourceCodeEtab')
+                    ->andWhere('etab.sourceCode = :sourceCodeEtab OR etab_substituant.sourceCode = :sourceCodeEtab')
                     ->setParameter('sourceCodeEtab', $filter->getValue());
             });
         $ecoleDoctoraleFilter = $this->getEcoleDoctoraleSearchFilter()
             ->setQueryBuilderApplier(function (SelectSearchFilter $filter, DefaultQueryBuilder $qb) {
                 $qb
-                    ->andWhere('ed.sourceCode = :sourceCodeED OR ed_structureSubstituante.sourceCode = :sourceCodeED')
+                    ->andWhere('ed.sourceCode = :sourceCodeED OR ed_substituant.sourceCode = :sourceCodeED')
                     ->setParameter('sourceCodeED', $filter->getValue());
             });
         $uniteRechercheFilter = $this->getUniteRechercheSearchFilter()
             ->setQueryBuilderApplier(function (SelectSearchFilter $filter, DefaultQueryBuilder $qb) {
                 $qb
-                    ->andWhere('ur.sourceCode = :sourceCodeUR OR ur_structureSubstituante.sourceCode = :sourceCodeUR')
+                    ->andWhere('ur.sourceCode = :sourceCodeUR OR ur_substituant.sourceCode = :sourceCodeUR')
                     ->setParameter('sourceCodeUR', $filter->getValue());
             });
         $origineFinancementFilter = $this->getOrigineFinancementSearchFilter();
@@ -156,7 +156,10 @@ class RapportActiviteSearchService extends SearchService
             ->leftJoin('ur.structure', 'ur_structure')->addSelect('ur_structure')
             ->leftJoinStructureSubstituante('etab_structure', 'etab_structureSubstituante')
             ->leftJoinStructureSubstituante('ed_structure', 'ed_structureSubstituante')
-            ->leftJoinStructureSubstituante('ur_structure', 'ur_structureSubstituante');
+            ->leftJoinStructureSubstituante('ur_structure', 'ur_structureSubstituante')
+            ->leftJoin('etab_structureSubstituante.etablissement', 'etab_substituant')
+            ->leftJoin('ed_structureSubstituante.ecoleDoctorale', 'ed_substituant')
+            ->leftJoin('ur_structureSubstituante.uniteRecherche', 'ur_substituant');
 
         return $qb;
     }
diff --git a/module/Soutenance/config/others/proposition.config.php b/module/Soutenance/config/others/proposition.config.php
index a0213560ed0d2f0bdabc07a72d939e79d3882ca8..55e6f2ed6567130ebf6ad02d617bd87c7ce88e2a 100644
--- a/module/Soutenance/config/others/proposition.config.php
+++ b/module/Soutenance/config/others/proposition.config.php
@@ -60,6 +60,7 @@ return [
                             PropositionPrivileges::PROPOSITION_VALIDER_ED,
                             PropositionPrivileges::PROPOSITION_VALIDER_UR,
                             PropositionPrivileges::PROPOSITION_VALIDER_BDD,
+                            PropositionPrivileges::PROPOSITION_REVOQUER_STRUCTURE,
                             PropositionPrivileges::PROPOSITION_PRESIDENCE,
 
                             PropositionPrivileges::PROPOSITION_DECLARATION_HONNEUR_VALIDER,
@@ -137,6 +138,15 @@ return [
                         PropositionPrivileges::PROPOSITION_VALIDER_BDD,
                     ],
                 ],
+                [
+                    'controller' => PropositionController::class,
+                    'action' => [
+                        'revoquer-structure',
+                    ],
+                    'privileges' => [
+                        PropositionPrivileges::PROPOSITION_REVOQUER_STRUCTURE,
+                    ],
+                ],
                 [
                     'controller' => PropositionController::class,
                     'action' => [
@@ -378,17 +388,31 @@ return [
                                 'options' => [
                                     'route' => '/valider-structure',
                                     'defaults' => [
+                                        /** @see PropositionController::validerStructureAction() */
                                         'controller' => PropositionController::class,
                                         'action' => 'valider-structure',
                                     ],
                                 ],
                             ],
+                            'revoquer-structure' => [
+                                'type' => Segment::class,
+                                'may_terminate' => true,
+                                'options' => [
+                                    'route' => '/revoquer-structure',
+                                    'defaults' => [
+                                        /** @see PropositionController::revoquerStructureAction() */
+                                        'controller' => PropositionController::class,
+                                        'action' => 'revoquer-structure',
+                                    ],
+                                ],
+                            ],
                             'refuser-structure' => [
                                 'type' => Segment::class,
                                 'may_terminate' => true,
                                 'options' => [
                                     'route' => '/refuser-PropositionController',
                                     'defaults' => [
+                                        /** @see PropositionController::refuserStructureAction() */
                                         'controller' => PropositionController::class,
                                         'action' => 'refuser-structure',
                                     ],
diff --git a/module/Soutenance/src/Soutenance/Assertion/PropositionAssertion.php b/module/Soutenance/src/Soutenance/Assertion/PropositionAssertion.php
index 27b09d2ab38d84c7e7743a209bc0725c239f6fd0..0831dad490223e933575260ff4266c4ce612140c 100644
--- a/module/Soutenance/src/Soutenance/Assertion/PropositionAssertion.php
+++ b/module/Soutenance/src/Soutenance/Assertion/PropositionAssertion.php
@@ -2,6 +2,7 @@
 
 namespace Soutenance\Assertion;
 
+use Soutenance\Entity\Etat;
 use These\Entity\Db\Acteur;
 use Application\Entity\Db\Role;
 use These\Entity\Db\These;
@@ -211,6 +212,21 @@ class PropositionAssertion implements  AssertionInterface {
                     default:
                         return false;
                 }
+            case PropositionPrivileges::PROPOSITION_REVOQUER_STRUCTURE:
+                if ($proposition->getEtat()->getCode() !== Etat::EN_COURS && $proposition->getEtat()->getCode() !== Etat::ETABLISSEMENT) return false;
+                switch ($role) {
+                    case Role::CODE_BDD :
+                        $validations_BDD  = $this->getValidationService()->getRepository()->findValidationByCodeAndThese(TypeValidation::CODE_VALIDATION_PROPOSITION_BDD, $these);
+                        return (!empty($validations_BDD) && $structure === $theseEtablissementStructure);
+                    case Role::CODE_RESP_UR :
+                        $validations_UNITE  = $this->getValidationService()->getRepository()->findValidationByCodeAndThese(TypeValidation::CODE_VALIDATION_PROPOSITION_UR, $these);
+                        return (!empty($validations_UNITE) && $structure === $these->getUniteRecherche()->getStructure());
+                    case Role::CODE_RESP_ED :
+                        $validations_ED  = $this->getValidationService()->getRepository()->findValidationByCodeAndThese(TypeValidation::CODE_VALIDATION_PROPOSITION_ED, $these);
+                        return (!empty($validations_ED) && $structure === $these->getEcoleDoctorale()->getStructure());
+                    default:
+                        return false;
+                }
             case PropositionPrivileges::PROPOSITION_PRESIDENCE:
                 switch($role) {
                     case Role::CODE_BDD :
diff --git a/module/Soutenance/src/Soutenance/Controller/PresoutenanceController.php b/module/Soutenance/src/Soutenance/Controller/PresoutenanceController.php
index bfd6e03ee557340fbfc8927d169638a650a0b3f0..60864591b6d7ad519ce5011cc6dc45c30237a5f3 100644
--- a/module/Soutenance/src/Soutenance/Controller/PresoutenanceController.php
+++ b/module/Soutenance/src/Soutenance/Controller/PresoutenanceController.php
@@ -11,12 +11,15 @@ use Application\Service\Role\RoleServiceAwareTrait;
 use Application\Service\Source\SourceServiceAwareTrait;
 use Application\Service\Utilisateur\UtilisateurServiceAwareTrait;
 use DateInterval;
+use Doctrine\ORM\Exception\ORMException;
+use Exception;
 use Fichier\Entity\Db\NatureFichier;
 use Fichier\Service\Fichier\FichierServiceAwareTrait;
 use Fichier\Service\Fichier\FichierStorageServiceAwareTrait;
 use Fichier\Service\Storage\Adapter\Exception\StorageAdapterException;
 use Individu\Entity\Db\Individu;
 use Individu\Service\IndividuServiceAwareTrait;
+use JetBrains\PhpStorm\NoReturn;
 use Laminas\Http\Response;
 use Laminas\Mvc\Plugin\FlashMessenger\FlashMessenger;
 use Laminas\View\Model\ViewModel;
@@ -118,6 +121,13 @@ class PresoutenanceController extends AbstractController
         $validationBDD = $this->getValidationService()->getRepository()->findValidationByCodeAndThese(TypeValidation::CODE_VALIDATION_PROPOSITION_BDD, $these);
         $validationPDC = $this->getValidationService()->getRepository()->findValidationByCodeAndThese(TypeValidation::CODE_PAGE_DE_COUVERTURE, $these);
 
+        /** Parametres ---------------------------------------------------------------------------------------------- */
+        try {
+            $deadline = $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DELAI_RETOUR);
+        } catch (Exception $e) {
+            throw new RuntimeException("Une erreur est survenue lors de la récupération de la valeur d'un paramètre", 0 , $e);
+        }
+
         return new ViewModel([
             'these' => $these,
             'proposition' => $proposition,
@@ -132,7 +142,7 @@ class PresoutenanceController extends AbstractController
             'justificatifsOk' => $justificatifsOk,
             'justificatifs' => $justificatifs,
 
-            'deadline' => $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DELAI_RETOUR),
+            'deadline' => $deadline,
 
             'autorisation' => $autorisation,
             'pv' => $pv,
@@ -182,11 +192,11 @@ class PresoutenanceController extends AbstractController
         $membres = $proposition->getMembres();
         $membre = $this->getMembreService()->getRequestedMembre($this);
 
-        /** Ici on prépare la liste des acteurs correspondant aux différents rôles pour le Select du formulaire
+        /** Ici, on prépare la liste des acteurs correspondant aux différents rôles pour le Select du formulaire
          *  d'association. On part du principe :
          *  - qu'un Rapporteur du jury est Rapporteur et Membre du jury,
-         *  - qu'un Rapporteur absent  est Rapporteur,
-         *  - qu'un Membre du jury     est Membre du jury.
+         *  - qu'un Rapporteur absent est Rapporteur,
+         *  - qu'un Membre du jury est Membre du jury.
          */
         $acteurs = $this->getActeurService()->getRepository()->findActeurByThese($these);
         $acteurs = array_filter($acteurs, function (Acteur $a) { return $a->estNonHistorise();});
@@ -235,7 +245,7 @@ class PresoutenanceController extends AbstractController
             $acteur = $this->getActeurService()->getRepository()->find($acteurId);
             $individu = $acteur->getIndividu();
 
-            if (!$acteur) throw new RuntimeException("Aucun acteur à associer !");
+            if (! isset($acteur)) throw new RuntimeException("Aucun acteur à associer !");
 
             //mise à jour du membre de soutenance
             $membre->setActeur($acteur);
@@ -455,7 +465,7 @@ class PresoutenanceController extends AbstractController
     }
 
     /** Document pour la signature en présidence */
-    public function procesVerbalSoutenanceAction()
+    #[NoReturn] public function procesVerbalSoutenanceAction(): void
     {
         $these = $this->requestedThese();
         $proposition = $this->getPropositionService()->findOneForThese($these);
@@ -473,7 +483,7 @@ class PresoutenanceController extends AbstractController
         exit;
     }
 
-    public function avisSoutenanceAction()
+    #[NoReturn] public function avisSoutenanceAction(): void
     {
         $these = $this->requestedThese();
         $proposition = $this->getPropositionService()->findOneForThese($these);
@@ -491,7 +501,7 @@ class PresoutenanceController extends AbstractController
         exit;
     }
 
-    public function rapportSoutenanceAction()
+    #[NoReturn] public function rapportSoutenanceAction(): void
     {
         $these = $this->requestedThese();
         $proposition = $this->getPropositionService()->findOneForThese($these);
@@ -509,7 +519,7 @@ class PresoutenanceController extends AbstractController
         exit;
     }
 
-    public function rapportTechniqueAction()
+    #[NoReturn] public function rapportTechniqueAction(): void
     {
         $these = $this->requestedThese();
         $proposition = $this->getPropositionService()->findOneForThese($these);
@@ -589,7 +599,7 @@ class PresoutenanceController extends AbstractController
     }
 
     /** Document pour la signature en présidence */
-    public function convocationsAction()
+    #[NoReturn] public function convocationsAction(): void
     {
         $these = $this->requestedThese();
         $proposition = $this->getPropositionService()->findOneForThese($these);
@@ -617,7 +627,7 @@ class PresoutenanceController extends AbstractController
         exit;
     }
 
-    public function convocationDoctorantAction()
+    #[NoReturn] public function convocationDoctorantAction(): void
     {
         $these = $this->requestedThese();
         $proposition = $this->getPropositionService()->findOneForThese($these);
@@ -643,7 +653,7 @@ class PresoutenanceController extends AbstractController
         exit;
     }
 
-    public function convocationMembreAction()
+    #[NoReturn] public function convocationMembreAction(): void
     {
         $these = $this->requestedThese();
         $proposition = $this->getPropositionService()->findOneForThese($these);
@@ -840,30 +850,34 @@ class PresoutenanceController extends AbstractController
         $proposition = $this->getPropositionService()->findOneForThese($these);
         $membres = $proposition->getMembres();
 
-        foreach ($membres as $membre) {
-            /** @var Acteur $acteur */
-            $source_code_acteur = 'SyGAL_Simulation_Rapporteur_' . $membre->getId();
-            $acteur = $this->getActeurService()->getRepository()->findOneBy(['sourceCode' => $source_code_acteur]);
-            if ($acteur !== null) {
-                $this->getActeurService()->getEntityManager()->remove($acteur);
-                $this->getActeurService()->getEntityManager()->flush($acteur);
-            }
+        try {
+            foreach ($membres as $membre) {
+                /** @var Acteur $acteur */
+                $source_code_acteur = 'SyGAL_Simulation_Rapporteur_' . $membre->getId();
+                $acteur = $this->getActeurService()->getRepository()->findOneBy(['sourceCode' => $source_code_acteur]);
+                if ($acteur !== null) {
+                    $this->getActeurService()->getEntityManager()->remove($acteur);
+                    $this->getActeurService()->getEntityManager()->flush($acteur);
+                }
 
-            /** @var Acteur $acteur */
-            $source_code_acteur = 'SyGAL_Simulation_Membre_' . $membre->getId();
-            $acteur = $this->getActeurService()->getRepository()->findOneBy(['sourceCode' => $source_code_acteur]);
-            if ($acteur !== null) {
-                $this->getActeurService()->getEntityManager()->remove($acteur);
-                $this->getActeurService()->getEntityManager()->flush($acteur);
-            }
+                /** @var Acteur $acteur */
+                $source_code_acteur = 'SyGAL_Simulation_Membre_' . $membre->getId();
+                $acteur = $this->getActeurService()->getRepository()->findOneBy(['sourceCode' => $source_code_acteur]);
+                if ($acteur !== null) {
+                    $this->getActeurService()->getEntityManager()->remove($acteur);
+                    $this->getActeurService()->getEntityManager()->flush($acteur);
+                }
 
-            /** @var Individu $source_code_individu */
-            $source_code_individu = 'SyGAL_Simulation_' . $membre->getId();
-            $individu = $this->getIndividuService()->getRepository()->findOneBy(['sourceCode' => $source_code_individu]);
-            if ($individu !== null) {
-                $this->getActeurService()->getEntityManager()->remove($individu);
-                $this->getActeurService()->getEntityManager()->flush($individu);
+                /** @var Individu $source_code_individu */
+                $source_code_individu = 'SyGAL_Simulation_' . $membre->getId();
+                $individu = $this->getIndividuService()->getRepository()->findOneBy(['sourceCode' => $source_code_individu]);
+                if ($individu !== null) {
+                    $this->getActeurService()->getEntityManager()->remove($individu);
+                    $this->getActeurService()->getEntityManager()->flush($individu);
+                }
             }
+        } catch (ORMException $e) {
+            throw new RuntimeException("Un problème est survenu en Base de donnée", 0 , $e);
         }
 
         return $this->redirect()->toRoute('soutenance/presoutenance', ['these' => $these->getId()], [], true);
diff --git a/module/Soutenance/src/Soutenance/Controller/PropositionController.php b/module/Soutenance/src/Soutenance/Controller/PropositionController.php
index c04a360dca2d58f44ef142415265c3d6513b07a3..8b7dd6a8e17258affb57c9bd2530e3ce6c361665 100644
--- a/module/Soutenance/src/Soutenance/Controller/PropositionController.php
+++ b/module/Soutenance/src/Soutenance/Controller/PropositionController.php
@@ -5,8 +5,10 @@ namespace Soutenance\Controller;
 use Application\Controller\AbstractController;
 use Application\Entity\Db\Role;
 use Application\Entity\Db\Utilisateur;
+use Application\Entity\Db\Validation;
 use Application\Service\Role\RoleServiceAwareTrait;
 use Application\Service\UserContextServiceAwareTrait;
+use Exception;
 use Fichier\Entity\Db\NatureFichier;
 use Fichier\Service\Fichier\FichierStorageServiceAwareTrait;
 use Individu\Entity\Db\Individu;
@@ -133,32 +135,20 @@ class PropositionController extends AbstractController
         /** @var IndividuRole[] $ecoleResponsables */
         $ecoleResponsables = [];
         if ($these->getEcoleDoctorale() !== null) {
-            // todo : utiliser findIndividuRoleByStructure(..., null, $these->getEtablissement())
-            $ecoleResponsables = $this->getRoleService()->findIndividuRoleByStructure($these->getEcoleDoctorale()->getStructure());
-            $ecoleResponsables = array_filter($ecoleResponsables, function (IndividuRole $ir) use ($these) {
-                return $ir->getIndividu()->getEtablissement() and $ir->getIndividu()->getEtablissement()->getId() === $these->getEtablissement()->getId();
-            });
+            $ecoleResponsables = $this->getRoleService()->findIndividuRoleByStructure($these->getEcoleDoctorale()->getStructure(), null, $these->getEtablissement());
         }
         /** @var IndividuRole[] $uniteResponsables */
         $uniteResponsables = [];
         if ($these->getUniteRecherche() !== null) {
-            // todo : utiliser findIndividuRoleByStructure(..., null, $these->getEtablissement())
-            $uniteResponsables = $this->getRoleService()->findIndividuRoleByStructure($these->getUniteRecherche()->getStructure());
-            $uniteResponsables = array_filter($uniteResponsables, function (IndividuRole $ir) use ($these) {
-                return $ir->getIndividu()->getEtablissement() and $ir->getIndividu()->getEtablissement()->getId() === $these->getEtablissement()->getId();
-            });
+            $uniteResponsables = $this->getRoleService()->findIndividuRoleByStructure($these->getUniteRecherche()->getStructure(), null, $these->getEtablissement());
         }
         /** @var IndividuRole[] $etablissementResponsables */
         $etablissementResponsables = [];
         if ($these->getEtablissement() !== null) {
-            // todo : utiliser findIndividuRoleByStructure(..., Role::CODE_BDD, $these->getEtablissement())
-            $etablissementResponsables = $this->roleService->findIndividuRoleByStructure($these->getEtablissement()->getStructure());
+            $etablissementResponsables = $this->roleService->findIndividuRoleByStructure($these->getEtablissement()->getStructure(), null, $these->getEtablissement());
             $etablissementResponsables = array_filter($etablissementResponsables, function (IndividuRole $ir) {
                 return $ir->getRole()->getCode() === Role::CODE_BDD;
             });
-            $etablissementResponsables = array_filter($etablissementResponsables, function (IndividuRole $ir) use ($these) {
-                return $ir->getIndividu()->getEtablissement() and $ir->getIndividu()->getEtablissement()->getId() === $these->getEtablissement()->getId();
-            });
         }
         $informationsOk = true;
         $directeurs = $this->getActeurService()->getRepository()->findEncadrementThese($these);
@@ -201,6 +191,18 @@ class PropositionController extends AbstractController
         /** Récupération des éléments liés au bloc 'intégrité scientifique' */
         $attestationsIntegriteScientifique = $this->getJustificatifService()->getJustificatifsByPropositionAndNature($proposition, NatureFichier::CODE_FORMATION_INTEGRITE_SCIENTIFIQUE);
 
+        /** Paramètres ---------------------------------------------------------------------------------------------- */
+
+        try {
+            $FORMULAIRE_DELOCALISATION = $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DOC_DELOCALISATION);
+            $FORMULAIRE_DELEGUATION = $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DOC_DELEGATION_SIGNATURE);
+            $FORMULAIRE_DEMANDE_LABEL = $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DOC_LABEL_EUROPEEN);
+            $FORMULAIRE_DEMANDE_ANGLAIS = $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DOC_REDACTION_ANGLAIS);
+            $FORMULAIRE_DEMANDE_CONFIDENTIALITE = $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DOC_CONFIDENTIALITE);
+        } catch (Exception $e) {
+            throw new RuntimeException("Une erreur est survenue lors de la récupération de paramètre.",0,$e);
+        }
+
         return new ViewModel([
             'these' => $these,
             'proposition' => $proposition,
@@ -224,11 +226,11 @@ class PropositionController extends AbstractController
             'informationsOk' => $informationsOk,
             'avis' => $this->getAvisService()->getAvisByThese($these),
 
-            'FORMULAIRE_DELOCALISATION' => $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DOC_DELOCALISATION),
-            'FORMULAIRE_DELEGUATION' => $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DOC_DELEGATION_SIGNATURE),
-            'FORMULAIRE_DEMANDE_LABEL' => $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DOC_LABEL_EUROPEEN),
-            'FORMULAIRE_DEMANDE_ANGLAIS' => $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DOC_REDACTION_ANGLAIS),
-            'FORMULAIRE_DEMANDE_CONFIDENTIALITE' => $this->getParametreService()->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DOC_CONFIDENTIALITE),
+            'FORMULAIRE_DELOCALISATION' => $FORMULAIRE_DELOCALISATION,
+            'FORMULAIRE_DELEGUATION' => $FORMULAIRE_DELEGUATION,
+            'FORMULAIRE_DEMANDE_LABEL' => $FORMULAIRE_DEMANDE_LABEL,
+            'FORMULAIRE_DEMANDE_ANGLAIS' => $FORMULAIRE_DEMANDE_ANGLAIS,
+            'FORMULAIRE_DEMANDE_CONFIDENTIALITE' => $FORMULAIRE_DEMANDE_CONFIDENTIALITE,
 
         ]);
     }
@@ -485,7 +487,7 @@ class PropositionController extends AbstractController
 
     }
 
-    public function validerStructureAction()
+    public function validerStructureAction(): Response|ViewModel
     {
         $these = $this->requestedThese();
         $proposition = $this->getPropositionService()->findOneForThese($these);
@@ -548,6 +550,67 @@ class PropositionController extends AbstractController
 
     }
 
+    public function revoquerStructureAction(): ViewModel
+    {
+        $these = $this->requestedThese();
+        $proposition = $this->getPropositionService()->findOneForThese($these);
+
+        /**
+         * @var Role $role
+         * @var Individu $individu
+         */
+        $role = $this->userContextService->getSelectedIdentityRole();
+
+        /** NOTE: pas de break ici pour dévalider en cascade */
+        $validations = [];
+        switch ($role->getCode()) {
+            case Role::CODE_RESP_UR :
+                $validations = array_merge($validations, $this->getValidationService()->getRepository()->findValidationByCodeAndThese(\Application\Entity\Db\TypeValidation::CODE_VALIDATION_PROPOSITION_UR,$these));
+            case Role::CODE_RESP_ED :
+                $validations = array_merge($validations, $this->getValidationService()->getRepository()->findValidationByCodeAndThese(\Application\Entity\Db\TypeValidation::CODE_VALIDATION_PROPOSITION_ED,$these));
+            case Role::CODE_BDD :
+                $validations = array_merge($validations, $this->getValidationService()->getRepository()->findValidationByCodeAndThese(\Application\Entity\Db\TypeValidation::CODE_VALIDATION_PROPOSITION_BDD,$these));
+        }
+
+
+        $validationsListing = "<ul>";
+        if (!empty($validations)) {
+            /** @var Validation $v */
+            foreach ($validations as $v) {
+                $validationsListing .= "<li>" . $v->getTypeValidation()->getLibelle() . " faite par" . $v->getHistoCreateur()->getDisplayName(). " le". $v->getHistoCreation()->format('d/m/y à H:i')."</li>";
+            }
+        }
+        $validationsListing .= "</ul>";
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            if ($data["reponse"] === "oui") {
+                if (!empty($validations)) {
+                    foreach ($validations as $v) {
+                        $this->getValidationService()->historise($v);
+                    }
+                }
+                $etat = $this->getPropositionService()->findPropositionEtatByCode(Etat::EN_COURS);
+                $proposition->setEtat($etat);
+                $this->getPropositionService()->update($proposition);
+            }
+        }
+
+        $this->getHorodatageService()->addHorodatage($proposition, HorodatageService::TYPE_VALIDATION, "Révocation " . $role->getCode());
+
+        $vm = new ViewModel();
+        if (!empty($validations)) {
+            $vm->setTemplate('default/confirmation');
+            $vm->setVariables([
+                'title' => "Révocation de votre validation",
+                'text' => "Cette révocation annulera les validations suivantes : " . $validationsListing . "Êtes-vous sûr&middot;e de vouloir continuer ?",
+                'action' => $this->url()->fromRoute('soutenance/proposition/revoquer-structure', ["these" => $these->getId()], [], true),
+            ]);
+        }
+        return $vm;
+    }
+
     public function refuserStructureAction(): ViewModel
     {
         $these = $this->requestedThese();
diff --git a/module/Soutenance/src/Soutenance/Provider/Privilege/PropositionPrivileges.php b/module/Soutenance/src/Soutenance/Provider/Privilege/PropositionPrivileges.php
index fcd9c56260870c76a981ecab28bfb1818b768f2d..754aafa71076112593a2786156493cf47e63d9c1 100644
--- a/module/Soutenance/src/Soutenance/Provider/Privilege/PropositionPrivileges.php
+++ b/module/Soutenance/src/Soutenance/Provider/Privilege/PropositionPrivileges.php
@@ -18,4 +18,5 @@ class PropositionPrivileges extends Privileges
     const PROPOSITION_SURSIS                          = 'soutenance-proposition-sursis';
     const PROPOSITION_DECLARATION_HONNEUR_VALIDER     = 'soutenance-declaration-honneur-valider';
     const PROPOSITION_DECLARATION_HONNEUR_REVOQUER    = 'soutenance-declaration-honneur-revoquer';
+    const PROPOSITION_REVOQUER_STRUCTURE              = 'soutenance-proposition-revoquer-structure';
 }
\ No newline at end of file
diff --git a/module/Soutenance/view/soutenance/proposition/partial/validations-structures.phtml b/module/Soutenance/view/soutenance/proposition/partial/validations-structures.phtml
index 78d39d17ba91d2cf19d06f2378005cde4cab9a98..4f81148025e5d95304a33446644c14d1dce5a78a 100644
--- a/module/Soutenance/view/soutenance/proposition/partial/validations-structures.phtml
+++ b/module/Soutenance/view/soutenance/proposition/partial/validations-structures.phtml
@@ -3,6 +3,7 @@
  * @var Proposition $proposition
  * @var Validation[][] $validations
  * @var boolean $canStructureValider
+ * @var boolean $canStructureRevoquer
  * @var boolean $canPresidence
  */
 
@@ -119,6 +120,16 @@ $these = $proposition->getThese();
                         </a>
                     </p>
                 <?php endif; ?>
+
+                <?php if ($canStructureRevoquer): ?>
+                    <p>
+                        <a <?php /** @see \Soutenance\Controller\PropositionController::revoquerStructureAction(); */ ?>
+                                href="<?php echo $this->url('soutenance/proposition/revoquer-structure', ['these' => $these->getId()], [], true); ?>"
+                                class="btn btn-warning action ajax-modal" data-event="modification">
+                            <span class="icon icon-unchecked"></span> Révoquer la validation
+                        </a>
+                    </p>
+                <?php endif; ?>
             </div>
         </div>
     </div>
diff --git a/module/Soutenance/view/soutenance/proposition/proposition.phtml b/module/Soutenance/view/soutenance/proposition/proposition.phtml
index 3df82acd3cdfc5aa673a6abb2aae77228eb02120..7e1d1fd09af6c54c3857af482526b45e92399a88 100644
--- a/module/Soutenance/view/soutenance/proposition/proposition.phtml
+++ b/module/Soutenance/view/soutenance/proposition/proposition.phtml
@@ -169,12 +169,16 @@ echo $this->partial('partial/validations-acteurs', [
 $canStructureValider = $isOk && $this->isAllowed($these, PropositionPrivileges::PROPOSITION_VALIDER_UR) ||
     $this->isAllowed($these, PropositionPrivileges::PROPOSITION_VALIDER_ED) ||
     $this->isAllowed($these, PropositionPrivileges::PROPOSITION_VALIDER_BDD);
+
+$canStructureRevoquer = $isOk && $this->isAllowed($these, PropositionPrivileges::PROPOSITION_REVOQUER_STRUCTURE);
+
 $canPresidence = $this->isAllowed($these, PropositionPrivileges::PROPOSITION_PRESIDENCE);
 
 echo $this->partial('partial/validations-structures', [
     'proposition' => $proposition,
     'validations' => $validations,
     'canStructureValider' => $canStructureValider,
+    'canStructureRevoquer' => $canStructureRevoquer,
     'canPresidence' => $canPresidence,
 ]); ?>
 
diff --git a/module/Structure/src/Structure/Form/Hydrator/EcoleDoctoraleHydrator.php b/module/Structure/src/Structure/Form/Hydrator/EcoleDoctoraleHydrator.php
index bef30331a041bb0de758d23e29223fdf31ac27bc..59f963dd8fc878d9558dcd437caaf29737786ee6 100644
--- a/module/Structure/src/Structure/Form/Hydrator/EcoleDoctoraleHydrator.php
+++ b/module/Structure/src/Structure/Form/Hydrator/EcoleDoctoraleHydrator.php
@@ -30,7 +30,7 @@ class EcoleDoctoraleHydrator extends StructureHydrator
         $theme = (isset($data['theme']) and trim($data['theme']) !== '') ? trim($data['theme']) : null;
         $offreThese = (isset($data['offre-these']) and trim($data['offre-these']) !== '') ? trim($data['offre-these']) : null;
 
-        if ($data['id'] === "") $data['id'] = null;
+        if (!isset($data['id']) || $data['id'] === "") $data['id'] = null;
 
         /** @var EcoleDoctorale $object */
         $object = parent::hydrate($data, $ed);
diff --git a/module/Structure/src/Structure/Form/Hydrator/EtablissementHydrator.php b/module/Structure/src/Structure/Form/Hydrator/EtablissementHydrator.php
index 5c86309f96a00c568d964b3c29064e390d8e269b..d97d02f3e05dc5fd9b08ecf1b4b103c03f3a3558 100644
--- a/module/Structure/src/Structure/Form/Hydrator/EtablissementHydrator.php
+++ b/module/Structure/src/Structure/Form/Hydrator/EtablissementHydrator.php
@@ -35,7 +35,7 @@ class EtablissementHydrator extends StructureHydrator
      */
     public function hydrate(array $data, $etablissement): Etablissement
     {
-        if ($data['id'] === "") $data['id'] = null;
+        if (!isset($data['id']) || $data['id'] === "") $data['id'] = null;
 
         /** @var Etablissement $object */
         $object = parent::hydrate($data, $etablissement);
diff --git a/module/Structure/src/Structure/Form/Hydrator/StructureHydrator.php b/module/Structure/src/Structure/Form/Hydrator/StructureHydrator.php
index 3a311d950735a322d975cce19e1c61dc296c35e6..f65626500f594133fee341ee37f2a24e8339c227 100644
--- a/module/Structure/src/Structure/Form/Hydrator/StructureHydrator.php
+++ b/module/Structure/src/Structure/Form/Hydrator/StructureHydrator.php
@@ -41,7 +41,7 @@ abstract class StructureHydrator extends DoctrineObject
         $object->getStructure()->setCode($data['code']);
         $object->getStructure()->setIdRef($data['id_ref']);
         $object->getStructure()->setIdHal($data['id_hal']);
-        $object->getStructure()->setCheminLogo($data['cheminLogo']);
+        $object->getStructure()->setCheminLogo($data['cheminLogo']??null);
         $object->getStructure()->setEstFermee(isset($data['estFerme']) and $data['estFerme'] === "1");
 
         return $object;
diff --git a/module/Structure/src/Structure/Form/Hydrator/UniteRechercheHydrator.php b/module/Structure/src/Structure/Form/Hydrator/UniteRechercheHydrator.php
index 59012bfe91c00155d4d5248d38fbb9a1d27c181e..8f94fae49a159fd668d28568232124a832568add 100644
--- a/module/Structure/src/Structure/Form/Hydrator/UniteRechercheHydrator.php
+++ b/module/Structure/src/Structure/Form/Hydrator/UniteRechercheHydrator.php
@@ -26,7 +26,7 @@ class UniteRechercheHydrator extends StructureHydrator
      */
     public function hydrate(array $data, $ur): UniteRecherche
     {
-        if ($data['id'] === "") $data['id'] = null;
+        if (!isset($data['id']) || $data['id'] === "") $data['id'] = null;
 
         /** @var UniteRecherche $object */
         $object = parent::hydrate($data, $ur);
diff --git a/module/These/src/These/Service/FichierThese/PdcData.php b/module/These/src/These/Service/FichierThese/PdcData.php
index fafc149008ceac66c93288264a44897eee901693..2a66b7d7574cd81bd61bb9acd19aa3d6bd8c6675 100644
--- a/module/These/src/These/Service/FichierThese/PdcData.php
+++ b/module/These/src/These/Service/FichierThese/PdcData.php
@@ -9,8 +9,7 @@ use These\Entity\Db\Acteur;
 /** Les informations ici sont des chaines de caractères */
 class PdcData
 {
-    /** @var string */
-    private $titre;
+    private ?string $titre = null;
     /** @var string */
     private $specialite;
     /** @var string */