# Audit fonctionnel, pages, routes et permissions

> Ce document conserve l'audit historique réalisé avant les phases de
> sécurisation. Le réaudit de l'état courant et la feuille de route active sont
> disponibles dans [AUDIT_2026-08-14.md](AUDIT_2026-08-14.md).

Date de l'audit : 14 août 2026  
Périmètre : application Flask `app_new`, modèles, templates, routes enregistrées, configuration Docker et tests.

## Résumé exécutif

L'application contient une base métier utile, mais elle n'est pas encore prête pour une utilisation multi-utilisateur en production. Les écrans principaux s'affichent, le patrimoine importé est riche et les notions de lots, tâches, équipements groupés/individuels, interventions, contrats, compteurs et consommables existent. En revanche, le contrôle d'accès n'est pratiquement pas appliqué aux routes métier, la protection CSRF est désactivée dans l'environnement réellement lancé, plusieurs écrans reposent sur des modèles incompatibles et l'arborescence des templates contient beaucoup de versions concurrentes.

Constats mesurés :

- 298 endpoints Flask enregistrés, route statique comprise ;
- 31 tests automatisés, tous réussis ;
- 125 références `url_for()` invalides dans l'ensemble des templates présents ;
- toutes les pages principales du menu testées répondent HTTP 200 ;
- `/setup-wizard/` et `/setup-wizard/admin` répondent HTTP 403 sur l'instance actuelle, car le marqueur de fin de setup et la base sont désynchronisés ;
- cinq blueprints complets sont exemptés de CSRF, et le mode développement désactive en plus le CSRF globalement.

## Cible fonctionnelle à retenir

Le noyau fonctionnel doit reposer sur les relations suivantes :

1. établissement → bâtiment → zone → salle/local → position précise facultative ;
2. catégorie d'équipement → lot de maintenance → tâches préventives ;
3. groupe quantitatif → sous-groupes localisés → unités individualisées si nécessaire ;
4. équipement → historique de localisation, pannes, réparations, compteurs, documents, consommables et contrats ;
5. tâche de lot → échéances par équipement, avec règles temporelles, compteur, météo ou événement ;
6. demande → diagnostic → intervention → pièces/temps → remise en service, réforme ou encombrants ;
7. intervention récurrente → analyse selon le type d'équipement et seuil d'alerte configurable ;
8. rôle assistant de prévention → plan d'actions, registres, contrôles, formations et suivi du temps dédié.

Règle de calendrier propre au collège : les vacances scolaires sont non travaillées par défaut. Le technicien peut toutefois travailler 2 à 3 jours au début ou à la fin des petites vacances, puis 5 à 10 jours au début et 5 à 10 jours à la fin des vacances d'été. Ces présences sont des dates exactes, pas une semaine-type : début, fin et pause peuvent changer chaque jour. Le moteur ne doit planifier aucune tâche pendant une fermeture, sauf sur une journée de présence explicitement déclarée et dans les horaires de cette date.

## Priorités bloquantes

### P0 — Sécurité et permissions

- Activer CSRF même en développement partagé. L'instance distante est exposée sur `0.0.0.0:5080` ; elle ne doit pas fonctionner comme un poste local isolé.
- Retirer les exemptions globales de `pronote`, `messagerie` et `scheduler`. L'API REST peut rester exemptée uniquement avec une authentification API robuste.
- Appliquer une permission à chaque route, pas seulement `login_required`.
- Réserver aux administrateurs : intégrations, secrets, IA, watchdogs, utilisateurs, données, purge et configuration système.
- Réserver aux responsables patrimoine : création/suppression des bâtiments, zones, salles, lots, catégories, entreprises et contrats.
- Réserver aux techniciens : modification des équipements, interventions, stocks, relevés et planification.
- Limiter les demandeurs à la création et au suivi de leurs propres demandes.
- Ajouter une journalisation d'audit immuable : utilisateur, action, objet, ancienne valeur, nouvelle valeur, date et adresse IP.
- Remplacer les suppressions physiques par archivage et imposer une permission distincte pour purger.

### P0 — Cohérence des rôles

Quatre vocabulaires incompatibles coexistent : `tech`, `technicien`, `technician`, ainsi que `demandeur`, `requester`, `user` et `viewer`. Le décorateur de permissions attend `technicien`, le formulaire principal crée `tech`, certaines requêtes cherchent `technician` et le modèle documente `user/viewer`. Il faut une seule énumération persistée et une migration des valeurs existantes.

Rôles proposés :

- `administrateur_systeme` : secrets, intégrations, sauvegardes et comptes ;
- `responsable_gmao` : référentiels, règles, contrats, tableaux de bord globaux ;
- `technicien` : patrimoine, interventions, planning, relevés et stocks ;
- `assistant_prevention` : module prévention et consultation des actions techniques liées ;
- `demandeur` : saisie et suivi de ses demandes ;
- `lecture` : consultation autorisée sans mutation.

Les permissions doivent être stockées ou dérivées de rôles stables. La page `/admin/permissions` est actuellement décorative : son POST n'enregistre rien.

### P0 — Intégrité métier

- Interdire qu'un identifiant d'objet fourni dans l'URL permette de modifier ou supprimer un objet sans contrôle métier.
- Vérifier les appartenances croisées : un compteur envoyé pour l'équipement A ne doit pas pouvoir modifier celui de B ; même exigence pour documents, restrictions, tâches, salles et interprétations.
- Uniformiser les statuts. Les équipements utilisent simultanément `actif`, `en_service`, `maintenance`, `en_maintenance`, `hors_service`, `hs`, `a_jeter`, `jete` et `retire`.
- Uniformiser `curatif/curative`, `preventif/preventive` et les statuts de tâches `planned/planifiee`.
- Ajouter des contraintes uniques et index utiles sur les codes, associations et objets de catalogue.
- Mettre les évolutions de schéma dans Alembic. `db.create_all()` ne remplace pas des migrations sur une base existante.

## Audit page par page et par famille de routes

### Authentification — `/auth/*`

Pages : connexion, profil, changement de mot de passe, utilisateurs.

Points positifs : validation des mots de passe à 12 caractères sur les formulaires récents, protection contre la redirection externe et blocage d'un utilisateur inactif.

À faire :

- supprimer le doublon fonctionnel entre `/auth/users*` et `/admin/users*` ;
- empêcher la suppression du dernier administrateur ;
- invalider les sessions après changement de mot de passe ou désactivation ;
- ajouter limitation des tentatives, délai progressif et journal de connexions ;
- ajouter propriété officielle `role_label` au modèle ;
- valider l'unicité email/nom lors d'une modification ;
- rendre le changement de rôle traçable et soumis à une permission dédiée.

### Administration — `/admin/*`

Pages : accueil, utilisateurs, permissions, personnel, types de salles, services, paramètres et gestion des données.

Défauts confirmés :

- `user_new` utilise `ROLES` sans l'importer : le POST peut produire une erreur 500 ;
- `update_permissions` n'enregistre rien ;
- `update_user_permissions` redirige vers un endpoint inexistant ;
- le template `admin/room_type_form.html` attendu n'existe pas ;
- les pages utilisateurs font doublon avec `/auth/users` ;
- la gestion des données permet des suppressions massives ; une simple confirmation textuelle ne remplace pas une autorisation renforcée ;
- la page des réglages génériques peut exposer toutes les valeurs d'`AppSettings`, y compris des secrets selon leur stockage.

À faire : fusionner l'administration dans un seul module, corriger les endpoints, mettre en place RBAC, masquer les secrets, ajouter confirmation par mot de passe pour les purges et rendre les suppressions récupérables.

### Setup initial — `/setup-wizard/*`

État après correction : le wizard possède dix étapes cohérentes, charge les bâtiments existants, ajoute zones et salles sans suppression implicite, et synchronise en dur 36 catégories et 91 lots issus du dump. Les associations catégorie–lot sont idempotentes.

Reste à faire :

- remplacer le fichier `.setup_complete` par un état transactionnel stocké en base ;
- fournir une commande administrative explicite pour rouvrir le wizard ;
- migrer `setup_progress.step` et déplacer le modèle dans les modèles/migrations ;
- ajouter CSRF au wizard après autorisation par jeton ;
- persister réellement horaires, vacances et jours fériés ;
- importer les périodes scolaires selon la zone académique, les fermer par défaut, puis permettre de rouvrir des dates de présence individuelles avec leurs horaires variables ;
- supprimer les endpoints de test ENT/Pronote retournant 501 ou les implémenter ;
- retirer les anciens templates `setup_wizard/admin.html` et routes imaginaires ;
- ne jamais supprimer automatiquement le compte `admin` lors de la création d'un autre administrateur ;
- rendre l'écriture du statut final atomique si un marqueur fichier est temporairement conservé.

### Tableau de bord, recherche et alertes — `/`, `/search`, `/alerts`, `/api/stats`

La page synthétise interventions, préventif, équipements, planning et interprétations. Elle est une bonne base mais plusieurs chiffres sont incomplets ou incohérents.

À faire :

- calculer réellement le stock bas ; il est actuellement fixé à zéro ;
- filtrer partout les objets archivés ;
- séparer les alertes personnelles des alertes globales ;
- relier les alertes à une règle, un responsable, une date d'acquittement et une résolution ;
- intégrer contrats arrivant à échéance, relevés en retard, lots présents sans équipement et équipements à pannes répétées ;
- rendre les cartes dépendantes des permissions ;
- réserver « créer les interventions du mois » au responsable/technicien et rendre l'opération idempotente avec une clé métier fiable.

### Messagerie unifiée — `/messagerie*`

L'écran agrège Outlook et ENT et permet interprétation/import manuel. Le blueprint est entièrement exempté de CSRF.

À faire : retirer l'exemption, séparer lecture/import/interprétation par permissions, garantir l'idempotence des imports, afficher la provenance et la confiance IA, exiger une validation humaine avant mutation GMAO, journaliser les décisions et empêcher qu'un contenu externe injecte du HTML ou des instructions non fiables.

### Interventions — `/interventions/*`

Fonctions existantes : liste filtrée, création individuelle/de groupe, détail, édition, statuts, commentaires, report, corbeille, restauration, planning et documents.

Défauts : toutes les mutations sont accessibles à tout utilisateur connecté ; certains templates référencent `interventions.restore` alors que l'endpoint enregistré est `interventions_planning.restore` ; plusieurs références documents sont obsolètes ; les statuts et types divergent entre constantes, formulaires et modèles.

À faire :

- distinguer demande, ordre de travail et intervention exécutée ;
- ajouter workflow contrôlé avec transitions autorisées par rôle ;
- saisir diagnostic, cause, action, temps prévu/réel, indisponibilité, coût, pièces, photos et validation ;
- lier une panne à l'unité précise ou au groupe quantitatif ;
- ajouter réouverture et clôture, avec motif ;
- traiter la mise en réparation temporaire puis remise en service ou réforme ;
- calculer la récurrence par équipement individuel, type de défaut et fenêtre temporelle ;
- appliquer une politique par catégorie : alerte travaux lourds pour prise/fenêtre/luminaire, simple statistique pour chaise ou graffiti ;
- corriger les routes/templates orphelins et ajouter tests de transition.

### Planning et préventif — `/planning/*`, `/scheduler/*`

Le projet possède plusieurs moteurs concurrents : `LotTask`, `PreventiveTask`, `ScheduledTask`, `PlanningItem`, interventions planifiées et planificateur automatique. Ils utilisent des noms de statuts et des relations différents.

À faire :

- choisir `LotTask` comme définition source, comme demandé ;
- générer une échéance par équipement, avec héritage du groupe et possibilité d'exception individuelle ;
- conserver un instantané de la tâche sur l'intervention afin qu'une modification future du lot ne réécrive pas l'historique ;
- prendre en charge déclencheurs calendrier, compteur, orage, gel, saison, événement et contrôle réglementaire ;
- gérer tolérance, anticipation, report justifié et prochaine échéance ;
- consolider les trois écrans de planning et supprimer les modèles redondants ;
- protéger les routes `/scheduler/run`, création mensuelle et changements de tâches ;
- réactiver CSRF sur le blueprint scheduler ;
- afficher charge disponible, congés, fermetures et temps prévention réservé.
- traiter séparément les journées de présence de début/fin de petites vacances et les deux plages de 5 à 10 jours des vacances d'été, sans recopier automatiquement les horaires d'un jour sur l'autre ;

### Patrimoine — `/equipments/*`

Fonctions existantes : arborescence groupe/enfants, quantité, individualisation, position, mouvement, historique de salles, catégories, documents, restrictions, compteurs, consommables et tâches planifiées.

Écarts avec la cible :

- aucun attribut persistant pour mobile/fixe ;
- numéro de série, fournisseur, prix d'achat et référence fournisseur ne sont pas dans le modèle principal malgré les besoins et certains textes d'interface ;
- le déplacement ne gère qu'une fiche entière, pas un transfert quantitatif entre deux sous-groupes de salles ;
- `individualized_quantity` contient une double boucle sur les mêmes enfants et peut surcompter ;
- `needs_deep_work` retourne toujours `False` ;
- la suppression « logique » peut devenir physique car elle teste un attribut `is_active` absent au lieu d'utiliser `is_deleted` ;
- la route de suppression physique efface aussi interventions et dépendances ;
- un changement d'état est effectué par GET sur `/equipments/<id>/status/<status>` ;
- les identifiants secondaires reçus par les routes compteurs, consommables, documents, restrictions et tâches ne sont pas toujours vérifiés par rapport à l'équipement de l'URL.

À faire :

- ajouter une opération transactionnelle « transférer N unités » entre salles ;
- ajouter `mobility_type` (`mobile`, `fixe`, `semi_mobile`) et bloquer les déplacements interdits ;
- ajouter identité technique facultative : série, fabricant, modèle, référence, fournisseur, prix, dates, garantie ;
- formaliser groupe global → groupe de salle → unité ;
- gérer retrait temporaire, atelier, prêt, réforme planifiée, encombrants et annulation ;
- conserver tous les historiques sans suppression physique ordinaire ;
- ajouter vues Catégorie → total → bâtiment → zone → salle ;
- intégrer une localisation précise seulement lorsque l'équipement est individualisé ;
- tester les invariants de quantité et empêcher quantité négative/double comptage.

### Bâtiments, zones, salles et types — `/equipments/buildings/*`, `/equipments/zones/*`, `/equipments/rooms/*`, `/room-types/*`

Les quatre référentiels existent. Le menu omet toutefois l'accès direct aux zones.

À faire :

- imposer unicité du nom de zone par bâtiment et du code de salle dans son périmètre ;
- empêcher une salle d'utiliser une zone d'un autre bâtiment ;
- refuser suppression si objets associés, avec fusion/déplacement explicite ;
- ajouter logements de fonction comme bâtiments ou sites typés, sans logique spéciale codée ;
- ajouter étage/secteur et plans facultatifs ;
- unifier les templates dupliqués et les endpoints obsolètes `equipments.room_detail`, `edit_room`, etc. ;
- compléter les types de locaux : classe, circulation, escalier, sanitaire, technique, extérieur, logement.

### Lots — `/lots/*` et ancien `/equipments/lots/*`

La page principale signale maintenant un lot présent sans équipement et permet de déclarer le lot non présent. Les tâches du dump sont disponibles dans `LotTask`.

Défauts : deux familles de routes gèrent les lots ; la page de détail référence `lots.task_detail`, inexistant ; l'édition ne couvre presque que l'entreprise et le motif d'absence ; la suppression est un placeholder.

À faire :

- garder uniquement `/lots/*` ;
- ajouter CRUD complet des tâches : libellé, périodicité, durée, déclencheur, contrat, responsable et consignes ;
- afficher nombre d'équipements directs et hérités ;
- distinguer « absent du site », « non vérifié » et « présent sans inventaire » ;
- ajouter action d'affectation massive du lot à une catégorie/groupe ;
- afficher conformité préventive et prochaines échéances ;
- ne jamais supprimer un lot référencé, seulement l'archiver.

### Compteurs — `/meters/*` et `/planning/meters*`

Deux interfaces concurrentes existent. Le modèle sait gérer seuils, intervalle de maintenance et fréquence de relevé.

À faire : fusionner les écrans, valider qu'un relevé ne diminue pas sauf remise à zéro documentée, calculer consommation entre relevés, alerter sur relevé manquant et seuil atteint, prévoir import CSV, afficher graphes hebdomadaires/mensuels/annuels et historiser corrections.

### Consommables, pièces et stocks — `/planning/consumables*`, `/parts/*`

Deux stocks concurrents existent (`Consumable` et `Part`). Le tableau de bord ne calcule pas encore les stocks bas.

À faire : définir un catalogue unique avec type consommable/pièce/outillage, mouvements de stock, lots et dates, fournisseur, prix, seuil, emplacement, réservation et consommation par intervention. Ne jamais modifier directement une quantité sans mouvement traçable.

### Entreprises et services — `/companies/*`, `/services/*`

La consultation/création fonctionne, mais les interfaces réellement rendues contiennent des liens vers des routes d'édition et d'association inexistantes. Il n'existe pas de contrôle de rôle.

À faire : CRUD complet, contacts multiples normalisés, spécialités, documents, évaluation, habilitations, contrats et historique d'interventions. Clarifier si « service » signifie service interne ou famille de prestations.

### Contrats — `/contracts/*`

Les contrats ont dates, reconduction, préavis, montant, entreprise et liaison lot/équipement. Il manque la périodicité réelle des visites et leur preuve d'exécution.

À faire : échéancier d'interventions contractuelles, SLA, contacts, pièces incluses, documents sécurisés, alertes préavis, renouvellement, coût prévu/réel et contrôle de couverture lot/équipement. Réserver création/modification/suppression aux responsables.

### Documents — `/documents/*` et `/equipments/.../documents/*`

Deux implémentations se chevauchent. Les extensions sont filtrées, mais il faut aussi vérifier contenu MIME, taille, nom, droits sur l'objet parent et chemin réel. Les liens template utilisent plusieurs anciens noms d'endpoints.

À faire : stockage central, métadonnées, versions, antivirus si exposition externe, journal des téléchargements, catégories documentaires, rétention et suppression logique. Les documents contractuels et sensibles doivent avoir des droits spécifiques.

### Formations — `/training/*`

Les GET s'affichent sur une base vide, mais la création construit `Training(title, max_participants)` alors que le modèle possède `name` et pas `max_participants`. L'inscription écrit `status` alors que le modèle possède `is_confirmed`. Les templates appellent détail, édition et désinscription inexistants.

Cette famille doit être reconstruite avant usage. Elle pourra ensuite servir aux habilitations et au module prévention.

### Contraintes — `/constraints/*` et restrictions équipement

Deux concepts se chevauchent : contraintes de salle et restrictions d'équipement. Toutes les mutations sont ouvertes à tout compte connecté.

À faire : définir une règle unique de disponibilité, provenance manuelle/Pronote/fermeture, priorité entre règles, plage de validité, justification et permissions. Vérifier systématiquement que la restriction supprimée appartient à l'équipement de l'URL.

### Outlook — `/outlook/*`

Fonctions : authentification appareil, comptes, dossiers, messages, pièces jointes, contexte, interprétations et synchronisations.

Risques : plusieurs synchronisations mutantes utilisent GET ; les opérations sont majoritairement seulement `login_required` ; les comptes et messages doivent être filtrés par propriétaire ; les données mail sont externes et non fiables ; les anciennes vues Outlook dupliquées contiennent des endpoints `outlook_test.*` inexistants.

À faire : POST pour synchroniser, contrôle de propriété partout, chiffrement vérifié, rotation/révocation des jetons, idempotence, quotas, pagination, purge et journal de décisions IA.

### ENT — `/ent/*`

La page de configuration principale existe, mais `/ent/sync` annonce explicitement que la synchronisation n'est pas implémentée. De nombreux templates alternatifs appellent des endpoints absents : credentials, gestion du personnel, suppression/import initial et pièces jointes.

À faire : choisir une seule interface, terminer la synchronisation, chiffrer les identifiants, contrôler les droits administrateur pour configurer, séparer messages par périmètre, rendre les imports idempotents et supprimer les templates morts.

### Pronote — `/pronote/*`

Connexion QR, salles, personnels, professeurs et plannings existent partiellement. Import planning retourne « non implémenté ». `sync-salles` et `disconnect` modifient la base via GET. Le blueprint entier est exempté de CSRF.

À faire : POST avec CSRF, administration uniquement, gestion d'expiration de session, rapprochement contrôlé des salles sans doublons, aperçu avant import, journal des changements et véritable import d'occupation des salles.

### Yeastar — `/yeastar/*`

Configuration URL/utilisateur/mot de passe, test, DND et watchdog existent. Les secrets sont chiffrés et les actions sensibles utilisent `system_admin_required`.

À faire : masquer totalement les secrets dans les réponses, valider schéma/HTTPS, gérer certificat et timeout, limiter les appels, journaliser les commandes, afficher clairement « configuré mais désactivé » et tester les droits des routes de lecture selon la sensibilité des extensions.

### IA et contexte GMAO — `/ai-config/*`, `/gmao-config/*`, `/chatbot/*`

Ces écrans sont visibles à tout utilisateur connecté alors qu'ils permettent de changer une clé globale, le modèle IA et les automatismes. Le chatbot est un placeholder à réponse fixe. La page IA effectue un appel réseau dès son affichage, ce qui ralentit et divulgue une activité inutile.

À faire : administration uniquement pour les secrets et automatismes, chiffrement unique des secrets, bouton de test explicite, contrôle des coûts, journal d'usage, validation humaine, protection contre prompt injection, minimisation des données envoyées et suppression/masquage du chatbot tant qu'il n'a pas de fonction métier fiable.

### Statut, santé, logs et notifications — `/health`, `/status/*`, `/logs/*`, `/api/notifications`

Le healthcheck public minimal est acceptable s'il ne divulgue pas de secrets. Le statut détaillé et les logs doivent rester administrateur. Actuellement `/logs/` est visible à tout compte connecté ; seule la purge est administrateur. Les notifications ENT sont globales, tandis qu'Outlook est filtré par utilisateur.

À faire : droits admin pour logs/statut détaillé, rétention automatique, pagination, export sécurisé, acquittement, corrélation, masquage des secrets et filtrage des notifications par destinataire.

### API REST et exports — `/api/v1/*`, `/exports/*`

L'API REST applique bien `X-API-Key` ou session malgré l'exemption CSRF. Une seule clé globale ne suffit pas pour un système durable.

À faire : clés hachées, scopes, expiration, rotation, propriétaire, journal, limitation de débit et pagination validée. Les exports doivent filtrer selon le rôle, être traçables, échapper correctement le CSV et proposer des plages de dates.

### Assistant de création d'équipements — `/wizard/equipments*`

Cet assistant répond directement au besoin de création en masse par bâtiment/zone/salle et lot. Il doit devenir l'entrée principale d'inventaire, mais avec aperçu transactionnel, contrôle des quantités, mobilité, individualisation sélective, codes uniques et possibilité d'annuler tout le lot créé.

## Module assistant de prévention à créer

Le projet ne contient pas encore de module cohérent couvrant le rôle d'assistant de prévention. Il faut au minimum :

- registre d'actions et observations avec priorité, pilote, échéance et preuve ;
- suivi des 13 agents, fonctions, expositions, habilitations et formations, avec accès strictement limité ;
- calendrier récurrent des visites, contrôles et réunions ;
- suivi du temps consacré, objectif hebdomadaire configurable et tableau d'écart ;
- accidents, incidents et presque-accidents avec actions correctives ;
- DUERP : unités de travail, risques, cotation, mesures existantes et plan d'action ;
- registres sécurité, exercices, vérifications périodiques et observations ;
- liens vers équipements, salles, interventions et documents ;
- rappels et exports de synthèse ;
- confidentialité renforcée : aucune donnée médicale dans les fiches ordinaires, droits dédiés et journal d'accès.

Les obligations réglementaires exactes doivent être validées séparément à partir des sources officielles à jour avant d'être figées dans le logiciel.

## Dette de templates et routes orphelines

L'application possède des templates à la fois dans `app_new/templates` et dans les dossiers de modules. La résolution Jinja peut donc choisir une version différente de celle que le développeur vient de modifier. Cela explique qu'une page fonctionne tandis qu'une copie voisine contient des liens cassés.

Plan de nettoyage :

1. relever pour chaque `render_template` le fichier réellement résolu ;
2. conserver une seule version par nom logique ;
3. corriger les 125 références d'endpoints absents dans les templates conservés ;
4. supprimer les templates morts dans un commit séparé après vérification ;
5. ajouter un test qui analyse tous les `url_for` statiques ;
6. ajouter un test de rendu GET pour chaque page navigable ;
7. ajouter un test 401/403/200 par rôle et par famille de routes ;
8. ajouter un test CSRF pour chaque mutation navigateur.

## Feuille de route recommandée

### Phase 1 — rendre le socle sûr

- RBAC unique et migration des rôles ;
- CSRF actif, méthodes HTTP corrigées et contrôles de propriété ;
- migrations Alembic complètes ;
- nettoyage des templates/routes ;
- journal d'audit ;
- tests de toutes les routes et sauvegarde/restauration testée.

### Phase 2 — fiabiliser le patrimoine

- hiérarchie site/bâtiment/zone/salle ;
- groupes quantitatifs et transferts partiels ;
- équipements individuels et données techniques ;
- workflow réparation/réforme ;
- documents, stocks et mouvements traçables.

### Phase 3 — unifier la maintenance

- définition unique des tâches dans les lots ;
- moteur d'échéances multi-déclencheurs ;
- interventions et historique immuable ;
- récurrence et alertes par politique de catégorie ;
- contrats et visites externes.

### Phase 4 — organisation et prévention

- charge et planning réel ;
- temps assistant de prévention ;
- agents, habilitations et formations ;
- DUERP, actions et registres ;
- tableaux de bord et exports adaptés aux rôles.

### Phase 5 — intégrations

- Outlook, ENT, Pronote et Yeastar terminés et cloisonnés ;
- watchdogs pilotés par configuration, déjà amorcé ;
- supervision, rétention des logs et alertes ;
- IA optionnelle, explicable et toujours validée par un humain avant action métier.

## Critères de disponibilité pour une première vraie utilisation

Le projet pourra être considéré prêt lorsque :

- aucune mutation n'est possible sans permission explicite ;
- toutes les routes navigateur mutantes sont protégées contre CSRF ;
- aucune route GET ne modifie l'état ;
- les 298 endpoints ont au moins un test d'accès ou sont retirés ;
- tous les liens des templates actifs ciblent un endpoint existant ;
- bâtiments, zones, salles, groupes et unités conservent leurs quantités et historiques ;
- les tâches de lot génèrent des échéances fiables sans doublons ;
- aucune tâche n'est planifiée pendant les vacances hors des dates de présence saisies, et la capacité quotidienne respecte les horaires particuliers de chaque date ;
- réparation, déplacement, réforme et récurrence sont testés ;
- sauvegarde et restauration MariaDB + documents + configuration sont testées ;
- les secrets ne sont ni affichés, ni journalisés, ni commités ;
- l'exploitation distante utilise un mode non-debug, cookies sécurisés derrière HTTPS et une configuration de production.
