Commit Graph
5 Commits
Author SHA1 Message Date
MichaelandClaude Opus 5 b608aa87cf Recueillir à l'embauche ce qu'exige le contrat
Créer un salarié demandait cinq champs. Le contrat, la déclaration et le
registre en réclament une vingtaine, et rien ne permettait de les saisir :
le sexe, le nom de naissance, le pays et le département de naissance, la
situation de famille, les personnes à charge, le téléphone fixe, le
complément d'adresse et l'heure d'embauche n'existaient pas en base.

La migration les ajoute, toutes facultatives : un dossier incomplet doit
pouvoir exister — c'est au registre de signaler ce qui lui manque, pas à
la base de refuser l'embauche. Seul l'envoi des plannings par SMS fait
exception : c'est un consentement, donc faux par défaut, la charge de la
preuve pesant sur l'employeur.

Le pays et le département de naissance sont des colonnes à part et non une
commune saisie librement : la déclaration sociale les demande séparément,
et les rétro-extraire échouerait au premier « Bar-le-Duc (Meuse) ».

Le formulaire devient un panneau latéral : une trentaine de champs posés
au centre masquaient l'annuaire, et on embauche en regardant qui est déjà
là. Le matricule y est proposé à la suite du dernier, attribué dans la
transaction pour que deux embauches simultanées ne tombent pas sur le même
rang. Le nom de naissance vaut le nom de famille quand il n'en diffère
pas, plutôt que d'imposer une ressaisie à l'immense majorité des dossiers.

Le responsable hiérarchique et la politique RTT se posent enfin à
l'embauche : les deux modèles existaient sans qu'aucun écran ne les
alimente.

Le registre unique du personnel gagne sa colonne « sexe » et se tient
désormais au nom de naissance — le nom d'usage peut changer sans que la
personne change.

La migration s'applique au redéploiement : l'entrypoint du conteneur passe
`prisma migrate deploy` avant de démarrer le serveur. Elle n'ajoute que des
colonnes nullables et deux types énumérés, sans réécriture de table.
Écrite et validée contre le schéma, non exécutée ici : aucune base n'était
ouverte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 17:34:10 +02:00
MichaelandClaude Opus 5 894e880198 Alléger l'annuaire
Le formulaire d'embauche, posé au bas de la liste, occupait plus de place
que l'effectif qu'on vient consulter — une quinzaine de champs déployés en
permanence pour un geste occasionnel. Il s'ouvre désormais en modale,
depuis le bouton d'en-tête.

`<dialog>` natif plutôt qu'un panneau maison : le piège de focus, la
fermeture par Échap et le fond inerte viennent avec, et une `<div>` doit
les réimplémenter sans jamais les tenir tout à fait.

Le tableau perd sa carte et ses fonds : une liste de personnes se lit
mieux sans cadre autour. Les colonnes suivent l'annuaire de référence —
collaborateur, rôle, email, mobile, rattachement, invitation. Le contrat
quitte le tableau, où il doublait le filtre qui le cherche déjà ; son
absence reste signalée là où elle compte, dans le rattachement.

Le décompte ne s'affiche plus que filtré : « 87 salariés » au-dessus de 87
lignes n'apprend rien.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 15:45:28 +02:00
MichaelandClaude Opus 5 91f3b240e1 Poser le contrat au moment de l'embauche
Créer un salarié demandait quatre champs et produisait un dossier vide :
sans contrat il n'apparaît sur aucune grille et ne se déclare pas, sans
équipe il ne s'ordonne nulle part — et jusqu'ici aucun écran ne permettait
de rattraper l'un ni l'autre.

Le contrat est proposé coché, et reste décochable : un remplaçant se
saisit parfois avant que son établissement soit tranché.

Dossier, contrat et rattachement entrent dans la même transaction. Créés
séparément, un incident au milieu laisserait exactement le dossier
incomplet que ce changement vise à supprimer.

Ouvrir un contrat reste une capacité distincte de celle de créer un
dossier : un gestionnaire d'annuaire n'engage pas l'entreprise. Le refus
le dit, et propose de créer le salarié sans contrat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 12:02:45 +02:00
MichaelandClaude Opus 5 5a113de02f Donner à l'annuaire une recherche et des filtres
Six colonnes et rien pour s'y retrouver : au-delà de vingt salariés,
l'effectif se parcourait au défilement. Recherche par prénom, nom ou
matricule, et quatre filtres — établissement, rôle, type de contrat,
présence — plus le tri.

Les critères vivent dans l'adresse et non dans le composant : un effectif
filtré s'envoie par lien, et le retour arrière défait le dernier choix
plutôt que de vider la page. Ils sont appliqués en base, pas après lecture :
plusieurs centaines de dossiers ne se filtrent pas en mémoire à chaque
affichage.

Le tri par nom reste en mémoire, lui : Postgres range « Étienne » après
« Etchegaray », un lecteur français avant.

Les colonnes suivent : rôle, mobile, rattachement et état de l'invitation
remplacent le matricule, qui ne s'affiche plus que sous le nom des salariés
sans compte applicatif — ceux pour qui c'est la seule adresse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 11:41:33 +02:00
Claude 2047d7f5cc Exiger un second facteur des rôles administrateur et RH
La matrice n° 15 l'impose ; les colonnes existaient en base depuis WP-01 mais
rien ne les remplissait. TOTP (RFC 6238) plutôt qu'un code envoyé par message :
le second facteur ne doit pas dépendre du canal qui sert déjà à réinitialiser le
mot de passe, faute de quoi un accès à la boîte donnerait les deux d'un coup.

L'algorithme est écrit ici plutôt qu'emprunté — trente lignes, et une dépendance
de moins sur le chemin d'authentification. Il est éprouvé contre les vecteurs
publiés de la RFC, ce qui distingue « le code change toutes les trente
secondes » de « le code est celui qu'attend l'application du téléphone ».

L'obligation est adossée aux capacités, pas à des rôles nommés qu'un client
renomme librement : distribuer les droits, ou lire les rémunérations. Elle est
tenue au point de passage de toutes les routes applicatives, où l'écran
d'enrôlement remplace le contenu. Il remplace plutôt qu'il ne redirige : une
redirection depuis un layout se joue aussi pendant la navigation qui suit la
connexion, et Next y répond par une page vide.

Le secret n'est enregistré qu'après qu'un code en a été tiré — l'enregistrer
d'avance laisserait des comptes porteurs d'un facteur que leur détenteur ne sait
pas produire, c'est-à-dire des comptes fermés. Le rejeu d'un code est refusé
dans sa propre fenêtre : sans cela le facteur protège d'un mot de passe volé,
pas d'un code lu par-dessus l'épaule.

Dix codes de secours accompagnent chaque activation, conservés hachés. Et parce
que PlanFlow est auto-hébergé et qu'il n'y a pas d'éditeur à appeler, un retrait
depuis le serveur existe — l'accès « break glass » que demande la même ligne de
la matrice. Sans lui, le second facteur deviendrait le risque principal plutôt
que la protection.

Un défaut trouvé par les tests, et il aurait été grave : la réactualisation de
la route après activation remplaçait l'écran par celui d'un compte déjà enrôlé,
emportant les codes de secours avant que leur destinataire ait pu les noter.

La suite de tests suit le produit : la mise en place enrôle réellement le compte
de direction et calcule les codes comme le ferait un téléphone. Les écrans qui
n'éprouvent pas l'authentification ont migré vers la session commune — deux
connexions parallèles sur un même compte se heurtent au refus de rejeu, ce qui
est le comportement voulu et non un défaut à contourner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cr9dkEHwbDgkWPnyGj1Rjv
2026-08-08 22:05:57 +00:00