Repository navigation
fix(api): changer le statut depuis l'admin par moveRoute - #625
Conversation
Two moves of the admin were missing from the life cycle, for the moderator only: unpublished → published (Republier, A-04) and needs_fix → unpublished (Dépublier). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Publish, request changes, reject and unpublish (A-02, A-04), republish (A-04) and the routes of a closed place (A-03) wrote routes.status directly. They now lock the whole row and call moveRoute as the moderator: a route that goes offline leaves the profiles that featured it, the first publication keeps its date, each withdrawal is dated and a republication clears it. The 409 already_decided stays checked before the move. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Plan suivi : deux commits autonomes, d'abord les transitions de |
|
Accord de niveau 2 consigné par MANAGER : Paul (opérateur) a validé cette PR en session le 2026-10-22, après la recette locale de l'admin (#621, sur |
Résultat et problème
Trois écritures de l'admin posaient
routes.statusdirectement, sansmoveRoute(apps/api/src/editor/lifecycle.ts), le seul écrivain prévu du statut. Conséquences surmain: un parcours dépublié restait mis en avant sur les profils (D-023),unpublished_atn'était ni daté ni vidé,published_atétait réécrit à chaque publication, et les transitions n'étaient pas vérifiées parcanMoveRoute.Maintenant :
decideRoute(moderation/decisions.ts: Publier, Demander des modifications, Refuser, Dépublier, A-02 et A-04),republishRoute(catalog/route-actions.ts: Republier, A-04) etclosePlace(reports/place-signals.ts: parcours d'un lieu fermé passésneeds_fix, A-03) lisent la ligne entière sousfor updateet appellentmoveRoute(tx, route, to, 'moderator', now), dans la transaction qui écrit déjàmoderation_actionsetadmin_actions.routeTransitions(packages/shared) gagne, pourmoderatorseulement :unpublished → publishedetneeds_fix → unpublished.already_decided(D-087) reste vérifié avantmoveRoute, avec le statut trouvé : la concurrence entre deux membres de l'équipe garde sa réponse, le 409conflictdemoveRouten'est jamais atteint par ces chemins.Acteur de la fermeture d'un lieu :
moderator. C'est une décision d'un membre de l'équipe, déjà journalisée à son nom (moderation_actions.actor_id,admin_actions), et la transitionpublished → needs_fixest ouverte aux deux acteurs :systemreste réservé au recalcul nocturne.À noter :
needs_fixn'est pas un statut public (publicRouteStatuses=published), donc un parcours passé à corriger par la fermeture d'un lieu ou par « Demander des modifications » sort aussi des profils, comme le veut la règle portée parmoveRoute. C'était déjà le cas d'un auteur ; c'est maintenant le cas de l'admin.Critères d'acceptation :
routes.statushors demoveRoutedansapps/api/src(hors seed et tests) :git grep -nE "update routes|\.update\(routes\)" -- 'apps/api/src/**/*.ts' ':!*.test.ts'ne laisse queeditor/lifecycle.ts(le statut),editor/save.ts(le contenu),catalog/route-actions.ts:81(reassignRouteToTeam, auteur seulement) etrecommendation/job.ts(le score)user_featured_routesdans la même transaction (test d'intégration)unpublished_at; Republier le vide et gardepublished_at; Publier garde la date d'une première publication (tests)needs_fixparmoveRoute, mise en avant retirée (test)canMoveRoute('unpublished', 'published', 'moderator')etcanMoveRoute('needs_fix', 'unpublished', 'moderator')vrais, et faux pour tout autre acteur (test exhaustif depackages/shared)already_decided, rien d'écrit deux fois (test existant, vert)Fixes #611
Écrans : A-02, A-03, A-04 (aucun changement visible)
Dépendance : aucune
Comment vérifier
pnpm turbo run lint typecheck --force(18 tâches) etprettier --check .verts en local@widoo/shared742 verts ;@widoo/admin199 verts ; API, les trois fichiers touchés (admin-moderation,admin-catalog,admin-signals) 54 verts. Suite API complète : 982 verts, 9 rouges danssearch-access.test.tsseul, vert relancé seul (instabilité en parallèle, Stabiliser la suite de tests de l'API quand ses fichiers tournent en parallèle #623)main(vérifié en retirant le correctif) : mise en avant retirée à la dépublication et à la fermeture d'un lieu, dates de publication et de retraitalready_decided, statut inchangéFormatage mécanique : non
Risque
Niveau : 2 — règle métier et intégrité des données (statut, dates, mise en avant), réversible, sans migration.
Revue OWASP ciblée (Top 10 2025) :
packages/shared; chaque changement se fait sous verrou de ligne, dans la transaction qui écrit l'historique et le journal ; les parcours d'un lieu fermé sont verrouillés dans un ordre stable (order by id). Tests ci-dessus.moderator, que seules les routes/admin/*emploient, derrièrerequireAdminSection(rôle lu en base, second facteur) ; un auteur ne peut ni republier ni dépublier un parcours à corriger (test exhaustif des refus).Taille : 3 lignes dans le premier commit, 175 dans le second (dont 116 de tests).
Retour arrière
Revert de la PR : les écritures reviennent directes, aucune migration. Les dates
unpublished_atposées entre-temps restent, sans effet sur l'ancien code. Les lignesuser_featured_routesretirées ne reviennent pas : l'auteur remet le parcours en avant depuis son profil.🤖 Generated with Claude Code