Naar hoofdinhoud gaan

Support

Tout logiciel a besoin d'un moyen pour ses utilisateurs de signaler des problemes et poser des questions. BeePass integre un systeme de tickets complet base sur Peppermint (un helpdesk open-source), enrichi par une couche d'IA qui genere automatiquement des brouillons de reponse a partir de votre documentation. Resultat : les questions courantes recoivent une reponse quasi-instantanee, et les administrateurs peuvent se concentrer sur les cas complexes.

Le module comprend la gestion des conversations, le suivi des SLA (Service Level Agreement --- les engagements de delai de reponse), les brouillons de reponse assistes par IA (RAG) et les operations en masse.


Architecture

Toutes les interactions support transitent par les API routes Next.js, qui servent d'intermediaire securise entre l'interface et Peppermint. Ni l'eleveur ni l'admin ne communiquent directement avec le serveur Peppermint --- c'est le backend Next.js qui s'en charge, en ajoutant l'authentification et le declenchement IA.

[Eleveur]  → /apps/tickets       → /api/support/tickets       → peppermintFetch() → Peppermint API :5003
[Admin] → /backoffice/support → /api/admin/support/tickets → peppermintFetch() → Peppermint API :5003

[Ticket POST] → Peppermint creation → generateAndPostDraft() (fire-and-forget)
├─ loadIndex() (lazy, data/rag-index.json)
├─ detectTicketLanguage() (FR/EN/DE/ES/IT/RU)
├─ searchRelevantChunks() (cosinus similarity, topK)
├─ generateDraftResponse() (Claude Haiku API, 90s timeout)
└─ peppermintFetch(POST comment) → [ai:BeePass IA]

[Comment user POST] → Peppermint commentaire → generateAndPostFollowUp() (fire-and-forget)
├─ Guard: authorType !== 'user' → skip
├─ Historique conversationnel (10 derniers messages)
├─ Claude Haiku API
└─ peppermintFetch(POST comment) → [ai:BeePass IA]

Toutes les requetes passent par les API routes Next.js (proxy server-side). Jamais d'appel direct client vers Peppermint. L'authentification admin utilise le cookie HMAC (verifyAdminFromRequest), l'eleveur utilise Supabase SSR.

Services Docker

ServiceImagePortDescription
beepass-peppermintpepperlabs/peppermint:latest3000 (frontend), 5003 (API)Helpdesk
beepass-peppermint-dbpostgres:17-alpine5432 (interne)PostgreSQL dedie Peppermint
beepass-ollamaollama/ollama:latest11434 (interne)Embeddings RAG (nomic-embed-text)

Liste des tickets

La vue principale affiche l'ensemble des tickets. C'est votre tableau de bord support quotidien --- d'un coup d'oeil, vous voyez quels tickets necessitent votre attention grace aux badges colores de statut et de SLA.

ColonneDescription
CheckboxSelection pour operations en masse
SujetTitre du ticket saisi par l'utilisateur
AuteurNom de l'utilisateur (avec avatar Supabase Storage)
StatutEtat courant avec badge colore
PrioriteNiveau d'urgence avec badge colore
Age (SLA)Badge colore : moins de 4h vert, 4-24h ambre, plus de 24h rouge. Tickets done : texte gris "Resolu"
DateHorodatage de la soumission
ActionsSupprimer (icone TbTrash)

Mapping statuts

Les statuts Peppermint sont traduits en libelles plus clairs dans l'interface :

PeppermintUI (i18n)Badge
needs_supportOuvertlightWarning
in_progressEn courslightInfo
in_reviewEn revuelightPrimary
doneResolulightSuccess

Mapping priorites

PeppermintBadge
lowlightSuccess
normallightPrimary
highlightWarning
urgentlightError

Filtres et recherche

  • 4 cards filtres : Total (primary), Ouvert (warning), En cours (info), Resolu (success)
  • Filtre "Ouvert" affiche tous les tickets non resolus (status !== 'done'), pas seulement needs_support
  • Recherche textuelle : filtrage par titre du ticket (InputPlaceholderAnimate)
  • Bouton Rafraichir : fetchTickets() force le rechargement

Actions groupees (Bulk Ops)

Quand vous avez plusieurs tickets a traiter de la meme facon (par exemple fermer tous les tickets resolus d'une semaine), les actions groupees evitent de le faire un par un :

ActionEndpoint (boucle sequentielle)Confirmation
Changement de statutPUT /api/admin/support/tickets/[id]/status x NNon (dropdown direct)
SuppressionDELETE /api/admin/support/tickets/[id] x NAlertDialog confirmation

Une barre flottante (AnimatePresence + motion.div) apparait quand des tickets sont selectionnes, avec compteur et progress bar pendant le traitement.

Traitement sequentiel

Peppermint n'a pas d'API bulk. Chaque ticket est traite un par un. Une barre de progression <Progress> s'affiche pendant l'operation.


Traitement d'un ticket

L'ouverture d'un ticket affiche la conversation complete entre l'utilisateur, les administrateurs et l'IA, dans un format de discussion chronologique.

Commentaires identifies (parsing prefixes)

Peppermint n'a qu'un seul compte admin interne. Pour distinguer qui a ecrit quoi, chaque commentaire est prefixe avant envoi avec l'identite de son auteur :

PrefixeAuteurBadge UIFond
[admin:NomAdmin]Administrateur"Admin" (lightPrimary)Standard
[user:NomUser]Utilisateur"Utilisateur" (lightWarning)Standard
[ai:BeePass IA] sans warningIA (doc trouvee)"IA" (bleu)bg-blue-50 dark:bg-blue-900/20
[ai:BeePass IA] avec warningIA (doc non trouvee)"Revue requise" (amber)bg-amber-50 dark:bg-amber-900/20

Le parsing utilise la regex ^\[(admin|user|ai):([^\]]+)\]\s* sur les routes GET detail.

Actions sur un ticket

ActionDescription
RepondreEnvoyer une reponse [admin:Nom] visible par l'utilisateur
Changer le statutSelect dropdown : 4 valeurs (needs_support, in_progress, in_review, done)
SupprimerAlertDialog confirmation, supprime aussi les notifications orphelines

Auto-transition de statut

Pour gagner du temps, quand un admin poste le premier commentaire sur un ticket needs_support, le statut passe automatiquement a in_progress (non-blocking, dans la route comment admin). Pas besoin de changer manuellement le statut.

SLA dans le detail

Le SLA (Service Level Agreement) mesure votre reactivite. Deux cartes inline sous le header du ticket affichent :

MetriqueCalculSeuils
Temps de reponsePremier commentaire admin non-IA - creationMoins de 4h vert, 4-24h ambre, plus de 24h rouge. "En attente" si pas de reponse
Temps de resolutionDernier commentaire - creation (si done)Moins de 24h vert, 24-72h ambre, plus de 72h rouge

Reponses IA (RAG)

L'objectif du RAG dans le support est simple : quand un eleveur pose une question dont la reponse existe dans votre documentation, pourquoi attendre qu'un admin la retrouve manuellement ? L'IA genere automatiquement un brouillon de reponse a chaque creation de ticket et a chaque commentaire utilisateur. Les brouillons apparaissent comme commentaires [ai:BeePass IA].

Fonctionnement du brouillon initial

Voici la sequence complete, du ticket a la reponse IA :

1. Ticket cree par l'eleveur

2. generateAndPostDraft() declenche (fire-and-forget, sans await)

3. loadIndex() — lazy load depuis data/rag-index.json

4. detectTicketLanguage(title + description) — 6 langues

5. searchRelevantChunks(query, topK) — embeddings Ollama + cosinus similarity

6. generateDraftResponse() — Claude Haiku API (90s timeout AbortController)

7. Decision matrix (3 formats selon pertinence + priorite)

8. peppermintFetch(POST comment) → [ai:BeePass IA] texte

Decision matrix (creation ticket)

Selon que la documentation contient ou non une reponse pertinente, et selon la priorite du ticket, le brouillon prend une forme differente :

Doc pertinente (score >= seuil)PrioriteFormatComportement
Ouilow / normalA (public)[ai:BeePass IA] Brouillon IA (a valider) : [reponse]
Ouihigh / urgentB (interne)Meme texte que A, visibilite interne
Non (score < seuil)ToutesC (interne)[ai:BeePass IA] Brouillon IA (reponse non trouvee) : [reponse] + warning

Follow-up IA sur commentaires eleveur

Quand un eleveur ajoute un commentaire a un ticket existant, l'IA repond automatiquement en tenant compte du contexte de la conversation (10 derniers messages). Le guard authorType !== 'user' empeche les boucles IA->IA et admin->IA --- seuls les messages d'eleveurs declenchent une reponse IA.

Detection de langue

Le support est multilingue (6 langues). L'IA detecte automatiquement la langue du ticket pour repondre dans la meme langue, via une heuristique dans detectTicketLanguage() :

  1. Cyrillique : texte contient [a-ya]{2,} -> Russe
  2. Caracteres distinctifs : n?! -> Espagnol, ssaou -> Allemand
  3. Mots-cles par langue (12 mots chacun)
  4. Defaut : Francais (si aucun match)

Le system prompt force la reponse dans la langue detectee.

Revue obligatoire

Les brouillons IA ne sont jamais envoyes automatiquement a l'utilisateur de maniere visible. L'administrateur doit systematiquement relire et valider le contenu. Les commentaires avec le badge "Revue requise" (amber) indiquent que la documentation n'a pas ete trouvee.

Configuration RAG

Les parametres du RAG (seuil de similarite, nombre de chunks, taille des chunks, prompts systeme) sont ajustables depuis la page Configuration IA.


SLA et metriques

Le suivi des temps de reponse et de resolution est essentiel pour garantir une qualite de service constante. Si les temps de reponse augmentent, c'est peut-etre le signe qu'il faut deleguer, embaucher ou ameliorer la documentation pour que l'IA reponde a plus de questions automatiquement.

Tous les calculs sont effectues cote client (pas de table DB supplementaire) a partir des timestamps des tickets et commentaires.

Seuils de couleur

MetriqueVertAmbreRouge
Age du ticketMoins de 4h4 -- 24hPlus de 24h
Temps de reponseMoins de 4h4 -- 24hPlus de 24h
Temps de resolutionMoins de 24h24 -- 72hPlus de 72h

KPIs du tableau de bord (AdminSupportKPIs)

Les metriques agregees sont visibles sur le tableau de bord principal pour un suivi sans ouvrir la page support :

KPIDescription
Tickets ouvertsNombre de tickets avec statut open ou in_progress
Tickets en coursNombre de tickets in_progress
Temps de reponse moyenMoyenne du temps de premiere reponse
Taux de resolutionPourcentage de tickets resolus

Le rafraichissement des KPIs support est effectue par polling toutes les 5 minutes (interval: 300000).


Notifications

Le systeme de notifications assure que personne ne rate un ticket important --- ni cote admin, ni cote eleveur.

Flux de notifications

ActionNotification pourTitre
Ticket creeTous les admins"Nouveau ticket support"
Admin repondAuteur du ticket"Reponse a votre ticket"
User repondTous les admins"Nouveau message ticket"
Ticket supprime---Notifications avec message_key=ticketId supprimees

Les notifications incluent des liens directs pour ouvrir le ticket en un clic :

  • Clic notification admin : router.push("/backoffice/support?ticket=ID") -> ticket auto-ouvert
  • Clic notification client : router.push("/apps/tickets?ticket=ID") -> ticket auto-ouvert
  • Mark-as-read par ticket_id : PATCH /api/admin/notifications avec { ticket_id } marque comme lues uniquement les notifications de ce ticket

Notification synthetique

Pour eviter que des tickets tombent dans l'oubli, le systeme genere une notification synthetique (calculee a la volee, pas stockee en base) "Tickets sans reponse" pour les tickets Peppermint ouverts depuis > 48h sans reponse admin.


Polling temps reel

Peppermint ne supporte pas les notifications push natives. Le systeme utilise donc du polling (interrogation periodique) pour garder l'interface a jour :

ContexteIntervalleMecanisme
Liste tickets admin30s/api/admin/support/tickets (silent refresh)
Liste tickets eleveur30s/api/support/tickets (silent refresh)
Commentaires (ticket ouvert)15s/api/admin/support/tickets/{id} (silent refresh)
Notifications admin30s/api/admin/notifications (fetch)

Le polling commentaires demarre uniquement quand un ticket est selectionne et s'arrete quand on revient a la liste.


Notes techniques

Dependance Peppermint

Le service Peppermint tourne dans un container Docker dedie, independant de l'application principale. Avant chaque appel API, la disponibilite du service est verifiee pour eviter des erreurs en cascade.

SituationComportement
Peppermint disponibleFonctionnement normal
Peppermint indisponibleLes routes retournent HTTP 503 avec un message explicite
Environnement dev/WindowsDocker non disponible : les routes support retournent systematiquement 503
Degradation gracieuse

La classe PeppermintUnavailableError gere la degradation gracieuse : les erreurs 503 liees a l'indisponibilite de Peppermint ne sont pas enregistrees dans api_error_logs pour eviter le spam d'emails de notification en developpement.

Proxy auto-login Peppermint

Le proxy server-side (src/lib/peppermint.ts) gere automatiquement l'authentification JWT (JSON Web Token --- un jeton d'acces securise) vers Peppermint :

  • Cache token : reutilise le token tant que > 5 min avant expiration
  • Auto-refresh : re-login transparent si le token expire

Endpoints Peppermint utilises

Endpoint PeppermintMethodeUtilise par
/api/v1/auth/loginPOSTAuto-login proxy
/api/v1/tickets/allGETAdmin liste tickets
/api/v1/ticket/{id}GETDetail ticket
/api/v1/ticket/createPOSTCreation ticket
/api/v1/ticket/commentPOSTAjout commentaire (body: {text, id})
/api/v1/ticket/status-updatePUTChangement statut admin
/api/v1/ticket/updatePUTResolution client + auto-transition
/api/v1/ticket/deletePOSTSuppression ticket (body: {id}) --- POST, pas DELETE
Fastify body vide

Peppermint utilise Fastify (un framework Node.js) qui rejette les requetes avec Content-Type: application/json et un body vide. C'est pourquoi la suppression utilise POST avec un body contenant l'id, pas la methode HTTP DELETE --- une particularite de cette API a garder en tete lors du debug.


API routes admin

EndpointMethodeAuthDescription
/api/admin/support/ticketsGETHMAC adminListe tous les tickets + avatars
/api/admin/support/tickets/[id]GETHMAC adminDetail ticket + commentaires parses
/api/admin/support/tickets/[id]DELETEHMAC adminSupprimer ticket + cleanup notifications
/api/admin/support/tickets/[id]/commentPOSTHMAC adminCommentaire [admin:Nom] + notification auteur + auto-transition statut
/api/admin/support/tickets/[id]/statusPUTHMAC adminChanger statut (4 valeurs valides)

API routes eleveur

EndpointMethodeAuthDescription
/api/support/ticketsGETSupabase SSRTickets filtres par email
/api/support/ticketsPOSTSupabase SSRCreer ticket + RAG auto-draft + notification admins
/api/support/tickets/[id]GETSupabase SSRDetail (verifie ownership email)
/api/support/tickets/[id]DELETESupabase SSRSupprimer (verifie ownership email)
/api/support/tickets/[id]/commentPOSTSupabase SSRCommentaire [user:Nom] + notification admins + RAG follow-up
/api/support/tickets/[id]/statusPUTSupabase SSRResolution uniquement (status: "done")

Variables d'environnement

VariableRequisDescription
PEPPERMINT_API_URLOuiURL interne Peppermint (Docker: http://beepass-peppermint:5003)
PEPPERMINT_ADMIN_EMAILOuiEmail admin Peppermint
PEPPERMINT_ADMIN_PASSWORDOuiMot de passe admin Peppermint
ANTHROPIC_API_KEYOuiCle API Anthropic pour Claude Haiku (RAG)
OLLAMA_URLOuiURL Ollama pour embeddings (http://beepass-ollama:11434)
OLLAMA_EMBED_MODELOuiModele embeddings (nomic-embed-text)
RAG_INDEX_PATHOuiChemin index disque (data/rag-index.json)