feat(feedback): integrate Feedback Hub widget in Settings #101
No reviewers
Labels
No labels
autopilot:pending-human
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-clarification
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/simpl-liste#101
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-68-feedback-widget"
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?
Fixes #68
Intègre le widget de feedback (Feedback Hub) dans l'app mobile.
Ce qui est fait
feedback.lacompagniemaximus.com/api/feedbackavecapp_id: simpl-listefeedback)Décisions produit (validées)
Tests
tests/feedback.test.mjs(node:test) : exécution réelle des helpers purs +sendFeedbackavecfetchstubbé (11 tests, verts)tests/smoke.test.cjs: guards statiques (app_id exactsimpl-liste, endpoint/api/feedback, cap 2000, service sans import)npx tsc --noEmit: vertNotes techniques
src/services/feedback.tsvolontairement sans aucun import : chargé par node:test via le type-stripping TS natif (Node 22.18+), qui ne résout pas l'alias@/. Le smoke test verrouille cette invariante.Review PR #101 — feat(feedback): integrate Feedback Hub widget
Verdict : APPROVE
Résumé
Intégration propre et bien testée du Feedback Hub dans Réglages > À propos. Aucun problème bloquant : la conformité Loi 25 (identité opt-in décochée par défaut), la whitelist de contexte, la gestion d'erreurs exhaustive et l'i18n fr/en sont tous corrects. Quelques suggestions non bloquantes ci-dessous.
Points vérifiés
user_id(sub Logto) envoyé uniquement si connecté ET coché.userIdprovient bien du store, alimenté parsetUserId(claims.sub)au sign-in (settings.tsx:111). Le checkbox d'identité ne s'affiche que siuserIdexiste. Conforme.sanitizeContext) alignée sur le serveur, valeurs tronquées à 500, champ omis si vide.sendFeedbackne throw jamais ; 400/429/5xx/réseau mappés vers des codes stables, l'UI ne tombe jamais dans un état indéfini.colors.priority.low,colors.terracotta.DEFAULT,colors.bleu.DEFAULTexistent tous ; classes Tailwind (bg-bleu, etc.) déjà utilisées ailleurs.feedbackcomplet dansfr.jsoneten.json, toutes les clés consommées existent.sendFeedbackavecfetchstubbé (succès, omission contexte, user_id, statuts d'erreur, réseau) + 4 guards statiques (endpoint, app_id, cap 2000, import-free).#68.Suggestions (non bloquantes)
Robustesse du timer d'auto-close (latent) — l'effet d'auto-close dépend de
onClose, passé par le parent en arrow inline() => setShowFeedback(false)(nouvelle référence à chaque render). Aujourd'hui l'écran Réglages n'a pas de re-render périodique, donc le timer 2s se déclenche correctement. Mais si Réglages adopte un jour le polling 500ms documenté (présent sur d'autres écrans), chaque re-render parent réinitialiserait le timer et l'écran de succès cesserait de se fermer seul. Durcissement bon marché :useCallbacksuronClosecôté parent, ou captureronClosedans une ref pour que l'effet ne dépende que deisSuccess.Plancher Node non déclaré —
npm testdépend désormais de Node ≥ 22.18 (type-stripping TS natif pour chargerfeedback.tsdepuis le.mjs). Pas de champengines, pas de.nvmrc, pas de CI pour l'imposer. Sur un Node plus ancien,node --test tests/feedback.test.mjséchoue à l'import du.ts. Ajouter"engines": { "node": ">=22.18" }(ou un.nvmrc) rendrait la contrainte découvrable.Guard import-free plus étroit que l'invariant —
staticImportsOfne matche queimport … from. Le chemin type-stripping casse aussi sur la syntaxe TS non-effaçable (enum, namespace, parameter properties,import x = require()) — aucune présente aujourd'hui. Le guard attrape la régression la plus probable (ajout d'un import@/), donc simple note.Double-submit possible sur un double-tap très rapide avant que l'état
sendingdésactive le bouton (même pattern que la modal de tags existante). Le rate-limit serveur (5/h) atténue. Pas de garde nécessaire.