Files
pta/docs/README_V7_27.md
2026-08-25 15:12:11 +02:00

7.4 KiB
Raw Permalink Blame History

PTA V7.27 — Le Service Enfance distribue les jetons des agents et des responsables

Le problème traité

Depuis la V7.11, tout compte d’accès passait par la DSI : création, jeton perdu, départ d’un remplaçant. Or c’est le Service Enfance qui sait qu’un agent est arrivé, qu’un responsable a laissé son jeton chez lui ou qu’un contrat s’arrête. Le détour par la DSI ajoutait un délai — parfois plusieurs jours — sans ajouter le moindre contrôle : la DSI ne pouvait rien vérifier de ce qu’on lui demandait, elle exécutait.

Ce qui change

L’onglet Administration du Service Enfance gagne une section « Jetons d’accès des agents et des responsables », sous les horaires de couverture. On y fait, pour ces deux rôles, ce que la page DSI permet :

  • créer un compte pour un agent ou un lieu qui n’en a pas encore ;
  • régénérer un jeton perdu ou compromis — l’ancien cesse aussitôt de fonctionner ;
  • désactiver puis réactiver un compte (départ temporaire) ;
  • supprimer un compte définitivement ;
  • générer en lot les jetons de toutes les identités actives qui n’en ont pas.

Comme sur la page DSI, un jeton produit n’est lisible qu’une fois, dans le panneau « Jetons à transmettre » : la base n’en garde qu’une empreinte SHA-256. Perdu, il ne se retrouve pas — il se régénère.

Ce qui ne change pas : la frontière de privilège

La délégation s’arrête à deux rôles : AGENT et RESPONSABLE_STRUCTURE. Les comptes SERVICE_ENFANCE et DSI n’apparaissent pas dans cette section, ne sont pas créables, et toute action qui en désigne un est refusée en 403. Ce n’est pas une commodité d’affichage :

  • un compte Service Enfance créé par le Service Enfance serait une auto-promotion — le rôle se distribuerait lui-même, sans contrôle extérieur ;
  • un compte DSI créé par le Service Enfance lui ouvrirait le journal d’activité, c’est-à-dire la trace de ses propres actions.

Le second facteur de la V7.12 reste hors de portée : ces deux rôles n’ont pas de mot de passe, et le Service Enfance n’a aucun moyen d’en effacer un. La réinitialisation de mot de passe reste une action DSI, sur la page DSI.

La borne est posée des deux côtés :

Où Quoi
AccessAccountController::ROLES_DELEGUES La liste blanche PHP, contrôlée avant toute écriture et à la relecture de tout compte désigné
CompteModel::lister(['roles' => …]) La liste SQL est bornée ; le filtre d’interface ne peut que restreindre à l’intérieur de cette borne
migration_v7_9h_jetons_service_enfance.sql La permission can_manage_field_access, accordée au seul Service Enfance

Une frontière de privilège ne doit pas dépendre d’un seul des deux côtés : une ligne mal saisie en base ne doit pas pouvoir ouvrir la création de comptes privilégiés, et inversement.

Traçabilité

Toutes les actions sont journalisées en catégorie ADMINISTRATION, avec le rôle de l’acteur et un contexte canal = DELEGATION_SERVICE_ENFANCE qui les distingue des mêmes actions faites par la DSI. Les refus le sont aussi, en ACCES_REFUSE : ROLE_HORS_PERIMETRE (création tentée sur un rôle privilégié) et COMPTE_HORS_PERIMETRE (action tentée sur un compte privilégié). La DSI garde donc la lecture complète de ce que le Service Enfance fait des accès.

Fichiers

Fichier Rôle
database/migration_v7_9h_jetons_service_enfance.sql Permission can_manage_field_access. Aucune page nouvelle : « Administration » est déjà ouverte au Service Enfance
app/Controllers/AccessAccountController.php Les cinq endpoints, la liste blanche et les refus
api/acces_comptes.php, acces_compte_creer.php, acces_compte_jeton.php, acces_compte_statut.php, acces_comptes_manquants.php Points d’entrée minces
app/Models/CompteModel.php Filtre roles sur lister()
app/Views/partials/administration.php La section et le panneau des jetons
assets/js/access-tokens.js Module accessTokens

V7.28 — Couper l’accès depuis la fiche des agents

La page Agents gagne, à côté de « Modifier », un bouton qui coupe ou rétablit l’accès de l’agent : « Couper l’accès » / « Rétablir l’accès ». C’est le geste courant — un départ, un arrêt long, un retour — là où la section « Jetons d’accès » de l’onglet Administration porte la distribution des jetons elle-même.

Ce bouton ne touche pas au jeton : désactiver puis réactiver rend le même jeton valable, et l’agent n’a rien à recevoir. Il ne touche pas non plus à la fiche de l’agent, qui reste planifiable — c’est l’accès à l’application qui est coupé, pas la personne au planning. Un agent qui n’a pas encore de compte affiche un bouton inerte « Sans compte d’accès », qui renvoie vers Administration : seul cet écran sait afficher un jeton fraîchement produit.

Aucun droit nouveau : le module agentAccess réutilise api/acces_comptes.php et api/acces_compte_statut.php, donc les mêmes gardes, la même liste blanche de rôles et la même journalisation. L’état des comptes n’est pas rendu par PHP mais chargé par le module — le HTML servi ne porte aucune information sur les comptes, comme sur l’écran DSI.

V7.29 — Un accès coupé retire l’agent des listes d’affectation

Couper l’accès d’un agent le retire désormais des listes où l’on affecte :

Écran Effet
Saisie (api/agents.php → AgentModel::listForLocation()) L’agent n’est plus proposé dans le sélecteur
Équipes (PageController::teams() → allSelectable()) L’agent n’est plus proposé à la composition

Trois bornes, toutes portées par le même NOT EXISTS de AgentModel::SANS_COMPTE_COUPE :

  • un agent SANS compte reste proposé. Il n’a pas encore reçu son jeton, ce qui est l’état normal avant distribution : le filtrer viderait les listes d’une installation neuve ;
  • le filtre porte sur compte_acces.actif, pas sur agent.actif : fermer une fiche d’agent et couper un accès restent deux décisions distinctes ;
  • les écrans de consultation (planning par agent, vue annuelle, PTA détaillé) et le référentiel Agents continuent de montrer l’agent. Sans quoi on ne pourrait plus ni relire son année passée, ni lui rétablir son accès — le bouton vit précisément sur cette page.

Ce qui n’est pas défait : les créneaux déjà saisis et les équipes déjà composées restent en place. Couper un accès n’efface rien du passé. En revanche, un lien profond qui désigne un agent coupé (file de validation, tableau de bord) ne peut plus le sélectionner : l’écran de saisie le dit alors explicitement, plutôt que de rester vide — rétablir l’accès rend la saisie de nouveau possible.

Correctif embarqué

CompteModel::lister() répétait le paramètre nommé :q quatre fois dans sa clause de recherche. PDO tourne ici sans émulation de requêtes préparées (ATTR_EMULATE_PREPARES = 0) : MariaDB refuse alors un même paramètre employé plusieurs fois. Toute recherche par nom, matricule ou début de jeton échouait en 500 sur la page DSI, depuis la V7.11. Les marqueurs sont désormais numérotés (:q_0 … :q_3). Le même champ de recherche existant dans la nouvelle section, le défaut aurait été reconduit tel quel.