@eqs/platform-next/client expose SignIn mais rien en face : chaque satellite doit écrire sa déconnexion à la main #56
Closed
opened 2026-09-11 14:26:00 +00:00 by nicolas-fryder
·
2 comments
No Branch/Tag specified
main
dev
@eqs/tooling@0.24.3
@eqs/testing@0.24.3
@eqs/telemetry@0.24.3
@eqs/platform-next@0.24.3
@eqs/platform-nest@0.24.3
@eqs/http@0.24.3
@eqs/errors@0.24.3
@eqs/config@0.24.3
@eqs/cli@0.24.3
@eqs/auth@0.24.3
@eqs/tooling@0.24.2
@eqs/testing@0.24.2
@eqs/telemetry@0.24.2
@eqs/platform-next@0.24.2
@eqs/platform-nest@0.24.2
@eqs/http@0.24.2
@eqs/errors@0.24.2
@eqs/config@0.24.2
@eqs/cli@0.24.2
@eqs/auth@0.24.2
@eqs/tooling@0.24.1
@eqs/testing@0.24.1
@eqs/telemetry@0.24.1
@eqs/platform-next@0.24.1
@eqs/platform-nest@0.24.1
@eqs/http@0.24.1
@eqs/errors@0.24.1
@eqs/config@0.24.1
@eqs/cli@0.24.1
@eqs/auth@0.24.1
@eqs/tooling@0.24.0
@eqs/testing@0.24.0
@eqs/telemetry@0.24.0
@eqs/platform-next@0.24.0
@eqs/platform-nest@0.24.0
@eqs/http@0.24.0
@eqs/errors@0.24.0
@eqs/config@0.24.0
@eqs/cli@0.24.0
@eqs/auth@0.24.0
@eqs/tooling@0.23.0
@eqs/testing@0.23.0
@eqs/telemetry@0.23.0
@eqs/platform-next@0.23.0
@eqs/platform-nest@0.23.0
@eqs/http@0.23.0
@eqs/errors@0.23.0
@eqs/config@0.23.0
@eqs/cli@0.23.0
@eqs/auth@0.23.0
@eqs/tooling@0.22.0
@eqs/testing@0.22.0
@eqs/telemetry@0.22.0
@eqs/platform-next@0.22.0
@eqs/platform-nest@0.22.0
@eqs/http@0.22.0
@eqs/errors@0.22.0
@eqs/config@0.22.0
@eqs/cli@0.22.0
@eqs/auth@0.22.0
@eqs/tooling@0.21.0
@eqs/testing@0.21.0
@eqs/telemetry@0.21.0
@eqs/platform-next@0.21.0
@eqs/platform-nest@0.21.0
@eqs/http@0.21.0
@eqs/errors@0.21.0
@eqs/config@0.21.0
@eqs/cli@0.21.0
@eqs/auth@0.21.0
@eqs/tooling@0.20.0
@eqs/testing@0.20.0
@eqs/telemetry@0.20.0
@eqs/platform-next@0.20.0
@eqs/platform-nest@0.20.0
@eqs/http@0.20.0
@eqs/errors@0.20.0
@eqs/config@0.20.0
@eqs/cli@0.20.0
@eqs/auth@0.20.0
@eqs/tooling@0.19.0
@eqs/testing@0.19.0
@eqs/telemetry@0.19.0
@eqs/platform-next@0.19.0
@eqs/platform-nest@0.19.0
@eqs/http@0.19.0
@eqs/errors@0.19.0
@eqs/config@0.19.0
@eqs/cli@0.19.0
@eqs/auth@0.19.0
@eqs/tooling@0.17.1
@eqs/testing@0.17.1
@eqs/telemetry@0.17.1
@eqs/platform-next@0.17.1
@eqs/platform-nest@0.17.1
@eqs/http@0.17.1
@eqs/errors@0.17.1
@eqs/config@0.17.1
@eqs/cli@0.17.1
@eqs/auth@0.17.1
@eqs/tooling@0.17.0
@eqs/testing@0.17.0
@eqs/telemetry@0.17.0
@eqs/platform-next@0.17.0
@eqs/platform-nest@0.17.0
@eqs/http@0.17.0
@eqs/errors@0.17.0
@eqs/config@0.17.0
@eqs/cli@0.17.0
@eqs/auth@0.17.0
@eqs/tooling@0.16.0
@eqs/testing@0.16.0
@eqs/telemetry@0.16.0
@eqs/platform-next@0.16.0
@eqs/platform-nest@0.16.0
@eqs/http@0.16.0
@eqs/errors@0.16.0
@eqs/config@0.16.0
@eqs/cli@0.16.0
@eqs/auth@0.16.0
@eqs/tooling@0.15.0
@eqs/testing@0.15.0
@eqs/telemetry@0.15.0
@eqs/platform-next@0.15.0
@eqs/platform-nest@0.15.0
@eqs/http@0.15.0
@eqs/errors@0.15.0
@eqs/config@0.15.0
@eqs/cli@0.15.0
@eqs/auth@0.15.0
@eqs/tooling@0.14.0
@eqs/testing@0.14.0
@eqs/telemetry@0.14.0
@eqs/platform-next@0.14.0
@eqs/platform-nest@0.14.0
@eqs/http@0.14.0
@eqs/errors@0.14.0
@eqs/config@0.14.0
@eqs/cli@0.14.0
@eqs/auth@0.14.0
@eqs/tooling@0.13.0
@eqs/testing@0.13.0
@eqs/telemetry@0.13.0
@eqs/platform-next@0.13.0
@eqs/platform-nest@0.13.0
@eqs/http@0.13.0
@eqs/errors@0.13.0
@eqs/config@0.13.0
@eqs/cli@0.13.0
@eqs/auth@0.13.0
@eqs/tooling@0.12.2
@eqs/testing@0.12.2
@eqs/telemetry@0.12.2
@eqs/platform-next@0.12.2
@eqs/platform-nest@0.12.2
@eqs/http@0.12.2
@eqs/errors@0.12.2
@eqs/config@0.12.2
@eqs/cli@0.12.2
@eqs/auth@0.12.2
@eqs/tooling@0.12.1
@eqs/testing@0.12.1
@eqs/telemetry@0.12.1
@eqs/platform-next@0.12.1
@eqs/platform-nest@0.12.1
@eqs/http@0.12.1
@eqs/errors@0.12.1
@eqs/config@0.12.1
@eqs/cli@0.12.1
@eqs/auth@0.12.1
@eqs/tooling@0.12.0
@eqs/testing@0.12.0
@eqs/telemetry@0.12.0
@eqs/platform-next@0.12.0
@eqs/platform-nest@0.12.0
@eqs/http@0.12.0
@eqs/errors@0.12.0
@eqs/config@0.12.0
@eqs/cli@0.12.0
@eqs/auth@0.12.0
@eqs/tooling@0.11.2
@eqs/testing@0.11.2
@eqs/telemetry@0.11.2
@eqs/platform-next@0.11.2
@eqs/platform-nest@0.11.2
@eqs/http@0.11.2
@eqs/errors@0.11.2
@eqs/config@0.11.2
@eqs/cli@0.11.2
@eqs/auth@0.11.2
@eqs/tooling@0.11.1
@eqs/testing@0.11.1
@eqs/telemetry@0.11.1
@eqs/platform-next@0.11.1
@eqs/platform-nest@0.11.1
@eqs/http@0.11.1
@eqs/errors@0.11.1
@eqs/config@0.11.1
@eqs/cli@0.11.1
@eqs/auth@0.11.1
@eqs/tooling@0.11.0
@eqs/testing@0.11.0
@eqs/telemetry@0.11.0
@eqs/platform-next@0.11.0
@eqs/platform-nest@0.11.0
@eqs/http@0.11.0
@eqs/errors@0.11.0
@eqs/config@0.11.0
@eqs/cli@0.11.0
@eqs/auth@0.11.0
@eqs/tooling@0.10.1
@eqs/testing@0.10.1
@eqs/telemetry@0.10.1
@eqs/platform-next@0.10.1
@eqs/platform-nest@0.10.1
@eqs/http@0.10.1
@eqs/errors@0.10.1
@eqs/config@0.10.1
@eqs/cli@0.10.1
@eqs/auth@0.10.1
@eqs/tooling@0.10.0
@eqs/testing@0.10.0
@eqs/telemetry@0.10.0
@eqs/platform-next@0.10.0
@eqs/platform-nest@0.10.0
@eqs/http@0.10.0
@eqs/errors@0.10.0
@eqs/config@0.10.0
@eqs/cli@0.10.0
@eqs/auth@0.10.0
@eqs/tooling@0.9.0
@eqs/testing@0.9.0
@eqs/telemetry@0.9.0
@eqs/platform-next@0.9.0
@eqs/platform-nest@0.9.0
@eqs/http@0.9.0
@eqs/errors@0.9.0
@eqs/config@0.9.0
@eqs/cli@0.9.0
@eqs/auth@0.9.0
@eqs/tooling@0.8.1
@eqs/testing@0.8.1
@eqs/telemetry@0.8.1
@eqs/platform-next@0.8.1
@eqs/platform-nest@0.8.1
@eqs/http@0.8.1
@eqs/errors@0.8.1
@eqs/config@0.8.1
@eqs/cli@0.8.1
@eqs/auth@0.8.1
@eqs/tooling@0.8.0
@eqs/testing@0.8.0
@eqs/telemetry@0.8.0
@eqs/platform-next@0.8.0
@eqs/platform-nest@0.8.0
@eqs/http@0.8.0
@eqs/errors@0.8.0
@eqs/config@0.8.0
@eqs/cli@0.8.0
@eqs/auth@0.8.0
@eqs/tooling@0.7.0
@eqs/testing@0.7.0
@eqs/telemetry@0.7.0
@eqs/platform-next@0.7.0
@eqs/platform-nest@0.7.0
@eqs/http@0.7.0
@eqs/errors@0.7.0
@eqs/config@0.7.0
@eqs/cli@0.7.0
@eqs/auth@0.7.0
@eqs/tooling@0.6.0
@eqs/testing@0.6.0
@eqs/telemetry@0.6.0
@eqs/platform-next@0.6.0
@eqs/platform-nest@0.6.0
@eqs/http@0.6.0
@eqs/errors@0.6.0
@eqs/config@0.6.0
@eqs/cli@0.6.0
@eqs/auth@0.6.0
@eqs/tooling@0.5.1
@eqs/testing@0.5.1
@eqs/telemetry@0.5.1
@eqs/platform-next@0.5.1
@eqs/platform-nest@0.5.1
@eqs/http@0.5.1
@eqs/errors@0.5.1
@eqs/config@0.5.1
@eqs/cli@0.5.1
@eqs/auth@0.5.1
@eqs/tooling@0.5.0
@eqs/testing@0.5.0
@eqs/telemetry@0.5.0
@eqs/platform-next@0.5.0
@eqs/platform-nest@0.5.0
@eqs/http@0.5.0
@eqs/errors@0.5.0
@eqs/config@0.5.0
@eqs/cli@0.5.0
@eqs/auth@0.5.0
@eqs/tooling@0.4.0
@eqs/testing@0.4.0
@eqs/telemetry@0.4.0
@eqs/platform-next@0.4.0
@eqs/platform-nest@0.4.0
@eqs/http@0.4.0
@eqs/errors@0.4.0
@eqs/config@0.4.0
@eqs/cli@0.4.0
@eqs/auth@0.4.0
@eqs/tooling@0.2.0
@eqs/telemetry@0.2.0
@eqs/errors@0.2.0
@eqs/config@0.2.0
@eqs/tooling@0.1.0
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
Infrastructure/eqs-platform#56
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Le socle fournit l'entrée dans la session (
SignIn) et ne fournit pas la sortie. Tout satellite qui pose un bouton « Déconnexion » doit donc écrire lui-même unfetchvers better-auth — c'est-à-dire dupliquer un bout de contrat que le socle possède déjà, et le dupliquer à trente exemplaires.Ce qui existe, et ce qui manque
node_modules/@eqs/platform-next/dist/client/index.d.ts:node_modules/@eqs/auth/dist/client.d.ts(réexporté par le précédent) :Cherché
signOut,sign-out,logout,deconnexdans les deux paquets et dans le client généré par orval : aucun résultat. Les routes better-auth ne figurent pas dansopenapi.json(elles ne sont pas décrites par le document de l'application), donc aucun client n'est généré pour elles non plus.Reproduction
Dans un satellite issu du gabarit, poser une barre de navigation avec un bouton de déconnexion. Il n'y a rien à appeler.
Ce que ça coûte
Le premier réflexe d'un agent de codage discipliné est de ne rien faire : la règle « aucun
fetchdirect, uniquement les clients générés » est dans l'AGENTS.mddu satellite, et l'endpoint n'est documenté nulle part côté client. Le nôtre a donc livré un lien visible mais inerte, en le signalant dans son rapport — ce qui est le bon comportement, et un mauvais produit : un bouton mort est pire qu'un bouton absent.Nous avons ensuite mesuré l'endpoint à la main :
et écrit le
fetchnous-mêmes, aveccredentials: 'include'(sans lui le cookie ne part pas, l'API ne sait pas qui se déconnecte, et l'appel rend 200 sans rien faire — un échec parfaitement silencieux) puis unwindow.location.assignpour qu'aucune donnée de la session précédente ne reste peinte à l'écran.Rien de tout cela n'était écrit quelque part. Chacune de ces trois décisions est un endroit où un satellite peut se tromper sans que rien ne le dise.
Ce que je proposerais
Par ordre de préférence :
SignOutsymétrique deSignIndans@eqs/platform-next/client, prenant le mêmebaseUrl, et remettantuseSession()à zéro en plus de poster. C'est le geste attendu, et le seul qui garantisse que l'état du provider et le cookie se vident ensemble.deconnecter(baseUrl)dans@eqs/auth/client, à côté dechargerMoi— les satellites gardent leur bouton, le socle garde la route, la méthode et lecredentials.credentials: 'include', ce qu'il faut faire de l'état client après) dans le README de@eqs/platform-next. C'est la solution la plus faible : elle laisse trente satellites réécrire la même chose, mais au moins ils la réécrivent juste.Accessoirement :
SignInprendbaseUrlet poste sur${baseUrl}/sign-in/email. Que le symétrique n'existe pas est d'autant plus surprenant que la mécanique, elle, est déjà là.Contournement posé chez nous, à retirer quand ce ticket sera traité
apps/web/src/components/coquille.tsx, fonctionBoutonDeconnexion— le seulfetchécrit à la main de toute l'interface, et son commentaire dit pourquoi.Versions
@eqs/platform-next,@eqs/auth: 0.8.1Trouvé en construisant la première vraie interface d'un satellite (Pilotage).
Vrai, et j'ai pris vos options 1 et 2 — elles ne sont pas concurrentes, elles sont à deux étages.
Votre paragraphe sur l'agent est le plus important du ticket, et je veux le reprendre tel quel :
C'est exactement ça. La règle était bonne, le produit était mauvais, et personne n'a fauté. Une lacune du socle devient un défaut de l'application, par obéissance. C'est ce qui en fait une classe et pas un oubli, et c'est consigné comme telle (chasse 12 de
reference/chasses.md).Les deux étages
deconnecter()dans@eqs/auth/client, à côté dechargerMoi: la route, la méthode, le corps, le cookie. Le mécanisme, écrit une fois.SignOutdans@eqs/platform-next/client, le pendant deSignIn. Il fait les trois gestes que vous avez dû retrouver un par un :sign-outavec le cookie ;useSession()à zéro — sinonuseCan()continue d'autoriser après la déconnexion ;C'est votre troisième point qui justifie que le composant existe plutôt qu'une simple fonction : vider la session ne démonte pas ce que les composants ont déjà affiché.
onDeconnectereprend la main sur cette décision quand le satellite sait ce qu'il fait ; par défaut, on navigue.Utilisable hors d'un
EqsProvider— il ne remet à zéro que ce qu'il trouve.Votre
credentialstouchait aussi le code existantC'est la partie que je ne cherchais pas. En écrivant
deconnecter, j'ai regardé commentchargerMois'y prenait :Le réglage était le défaut d'un paramètre. Passer le moindre
init— un en-tête, unsignal— le perdait, et l'appelant se retrouvait avec un/moien 401, donc « vous n'êtes pas connecté », sans rien pour l'expliquer. Le même échec silencieux que le vôtre, dans l'autre sens, et personne ne l'avait signalé parce que personne n'avait encore passé d'init.Il est maintenant appliqué après l'
init: l'omission ne coûte plus rien, etcredentials: 'omit'reste possible pour qui le veut vraiment.Éprouvé en le retirant : deux cas rougissent, un par fonction.
Votre option 3
Elle devient sans objet — il n'y a plus rien à réécrire, donc plus rien à documenter pour que trente satellites le réécrivent juste. Ce qui reste documenté, c'est le pourquoi : les commentaires de
deconnecteret deSignOutportent les trois décisions et le piège du cookie.Ce que ça change chez vous
BoutonDeconnexiondansapps/web/src/components/coquille.tsx— votre seulfetchécrit à la main — se remplace par :Si votre API est sur une autre origine,
baseUrl={${apiBaseUrl(process.env.NEXT_PUBLIC_API_URL ?? '')}/api/auth}, comme pourSignIn.Ce que je n'ai pas fait
Votre remarque de fin mérite sa réponse : les routes better-auth ne sont dans aucun contrat.
openapi.jsonne les décrit pas, donc aucun client n'est généré pour elles, donc tout ce qui les touche sera toujours écrit à la main quelque part. Je n'ai pas cherché à les faire entrer dans le document — c'est un vrai sujet, avec un effet sur le contrat servi et sur les clients de toute la flotte. Autant que ce « quelque part » soit le socle, ce qui est maintenant le cas pour les deux gestes qui comptent.Et l'inventaire des autres paires n'est pas fait :
defineTarget/oublierCibles,eqs e2e up/down,preparerCleet sa révocation. Certaines existent, aucune n'a été vérifiée comme paire. C'est écrit dans la chasse 12 avec le signe à chercher — un satellite qui écrit unfetchà la main, ou un bouton inerte.Branche
chasse/knip-et-code-mort. Ticket laissé ouvert jusqu'à la publication.connect ETIMEDOUT 127.0.0.1:<port éphémère>quand la suite complète tourne — jamais fichier par fichier #57eqs checktype-vérifie le front mais ne le compile jamais : toute une classe de défauts échappe à la porte #53AGENTS.mddu template affirme « Push surmain→ Coolify » comme un fait, alors qu'un satellite neuf n'est déployé nulle part #61refuser-genere.mjsrefuse toutprisma/migrations/**, y compris un squelette--create-onlyjamais appliqué : aucune DDL sur-mesure (trigger, fonction, vue, contrainte) n'est possible par la voie documentée #64Corrigé.
@eqs/platform-next/clientexporteSignOutet sesOptionsSignOut(packages/platform-next/src/client/index.tsx) : la paire est complète, plus aucun satellite n'écrit sa déconnexion à la main.Ce ticket a aussi fait bouger une règle du dépôt, et c'est écrit dans
AGENTS.md: « un bouton de déconnexion livré inerte parce que la règle interdisait lefetchqui manquait au socle (#56) ». C'est l'un des trois cas qui ont fondé le principe « le signe qu'une règle est à revoir : quelqu'un a dû contourner un garde-fou pour faire la chose juste ».Fermé après vérification contre le code de
devle 2026-09-21. Ce ticket restait ouvert faute d'unCloses #56dans le commit, pas faute de correctif.