---
title: "Connecteur GLPI"
module: store
type: functional
status: active
updated: 2026-08-18
---

# Connecteur GLPI

## Vue d'ensemble

Le connecteur GLPI permet de synchroniser de façon **bidirectionnelle** les tickets entre ISI-APP (module Isi-Ticket) et une instance **GLPI** (par exemple MY WIDIP). Un ticket créé dans ISI-APP est répliqué dans GLPI, et inversement, avec ses commentaires, sa solution et ses pièces jointes. Les statuts, priorités et catégories sont traduits dans les deux sens via des **tables de correspondance** configurées par le client.

Le connecteur s'inscrit dans le **Store de connecteurs** ISI-APP, au même titre que le connecteur OCS Inventory.

## À qui s'adresse ce connecteur

- Clients utilisateurs du module Isi-Ticket qui exploitent **également** une instance GLPI (interne ou hébergée chez un partenaire type WIDIP).
- Équipes IT qui veulent garder ISI-APP comme front utilisateur tout en alimentant un GLPI back-office (ou inversement).
- Cas typique : un MSP qui gère plusieurs clients dans GLPI mais propose ISI-APP comme portail à ses clients finaux.

## Activation

Le connecteur GLPI apparaît dans le **Store** d'ISI-APP (`/admin/store/connecteurs`). L'admin local du tenant l'installe pour son entité, ce qui crée une `StoreInstance` rattachée. Une fois installé :

- Une nouvelle entrée apparaît dans la page **GLPI** (`/glpi`) listant l'instance.
- L'admin clique sur l'instance pour accéder à la page de gestion (3 onglets : Synchronisation, Santé, IDs liés). Le paramétrage et les correspondances se règlent depuis **Store — Correspondances** (un lien y mène depuis la page).

Si aucune instance n'est encore créée, la page `/glpi` affiche un état vide invitant à passer par le Store.

### Accès réservé aux administrateurs

L'onglet **« Synchro GLPI »** de la sidebar et l'ensemble des pages `/glpi/*` sont **réservés aux administrateurs locaux du tenant** (profils `100`/`110`/`150` ou membres Isi-DSI, via `isAdminLocalUser()`). Un utilisateur standard ne voit pas l'entrée de menu et se voit refuser l'accès (HTTP 403) s'il tente d'ouvrir une URL GLPI directement. Cette page étant purement technique (paramétrage de synchronisation), elle n'a pas vocation à être exposée aux utilisateurs finaux.

## Écrans de gestion

La gestion se répartit sur deux écrans :

- **Store — Correspondances** (`/store/instances/{id}/mapping`) : 2 onglets — Paramétrage et Correspondances ;
- **Page de l'instance** (`/glpi/{id}`) : 3 onglets — Synchronisation, Santé et IDs liés.

### 1. Paramétrage (Store — Correspondances)
Configuration technique de la connexion à GLPI :

| Champ | Description |
|---|---|
| URL API GLPI | URL complète de l'API REST (ex : `https://glpi.client.fr/apirest.php`). Doit être en HTTPS. |
| App Token | Jeton applicatif fourni par GLPI. Stocké chiffré, jamais affiché en clair. |
| User Token | Jeton utilisateur fourni par GLPI. Idem. |
| Fréquence de synchro | Manuelle, 5 / 10 / 20 / 60 minutes |
| Mode utilisateur | `Anonyme`, `Par email`, `Reprise manuelle` (voir ci-dessous) |
| Envoi des mails | `ISI-APP` ou `GLPI` — qui envoie les notifications pour éviter les doublons |
| Sujets à envoyer vers GLPI | Périmètre de la synchronisation ISI-APP → GLPI. Vide = tous les sujets |
| Clôturer dans GLPI les tickets sortis du périmètre | Voir [Périmètre des sujets](#périmètre-des-sujets-envoyés-vers-glpi). Désactivé par défaut |
| IP autorisée | Optionnel, restreint l'accès API à une IP donnée |

Un bouton **"Tester la connexion"** valide les paramètres en direct sans sauvegarder.

### 2. Correspondances (Store — Correspondances)
Trois tables de mapping à renseigner par le client :

- **Catégories** — lie chaque catégorie de ticket ISI-APP à une catégorie GLPI (`itilcategories_id`), avec son type (Incident ou Demande). Une catégorie peut être marquée "par défaut" pour servir de filet en cas de catégorie non mappée.
- **Statuts** — lie les statuts ISI-APP (ouvert, en cours, résolu, clôturé) aux 6 statuts GLPI (Nouveau, En cours attribué, En cours planifié, En attente, Résolu, Clos).
- **Priorités** — lie les 5 niveaux de priorité ISI-APP au triplet GLPI (priorité, impact, urgence).

Les listes GLPI sont chargées à la volée via l'API au moment où l'utilisateur ouvre l'onglet.

### 3. Synchronisation (`/glpi/{id}`)
- Badge de statut de connexion (vert/rouge selon test live).
- Date de la dernière synchronisation réussie.
- Bouton **"Synchroniser maintenant"** pour déclencher une sync manuelle (utile pour tester ou rattraper après une coupure).
- Tableau des **50 derniers logs de synchronisation** : date, type d'objet (ticket, entité, utilisateur, pièce jointe…), sens (ISI→GLPI ou GLPI→ISI), statut (succès / erreur / avertissement), message détaillé.

### 4. Santé (`/glpi/{id}`)
Indicateurs de bon fonctionnement de l'instance (connexion, dernières synchronisations, anomalies récentes).

### 5. IDs liés (`/glpi/{id}`)
Tableau lecture seule listant toutes les correspondances d'identifiants (objets ISI-APP ↔ objets GLPI). Utile pour le support et le débogage. Filtrable par type d'objet — la liste des types proposés reflète ceux réellement présents pour l'instance (tickets, entités, utilisateurs, commentaires, tâches, solutions, demandeurs, documents et images, dans les deux sens). Exportable en CSV.

## Comportement de la synchronisation

### Sens GLPI → ISI-APP
Le connecteur récupère les tickets GLPI modifiés depuis la dernière synchro. Pour chacun :
- S'il existe déjà côté ISI-APP (table de correspondance d'IDs), il est mis à jour.
- Sinon, il est créé dans ISI-APP et la correspondance est enregistrée.
- Les commentaires (follow-ups), la solution et les pièces jointes suivent.

Les actions suivantes, réalisées **dans GLPI**, sont répercutées dans ISI-APP :

| Action dans GLPI | Effet dans ISI-APP |
|---|---|
| Changement de statut, titre, description, priorité, catégorie, entité | Ticket mis à jour |
| Ajout d'un suivi | Nouveau commentaire dans le fil du ticket |
| **Ajout, modification ou suppression d'une tâche** | La tâche est créée, mise à jour ou retirée du ticket ISI-APP (voir [Tâches](#tâches)) |
| **Correction du texte d'un suivi** | Le commentaire correspondant est mis à jour |
| **Suppression d'un suivi** | Le commentaire est retiré du fil du ticket |
| Ajout d'une solution | Commentaire « [Solution] » et passage du ticket en résolu/clos selon le statut |
| **Clôture du ticket** | Ticket clôturé, avec **réponse de clôture** reprise de la solution GLPI. Si le statut est passé à « Clos » sans solution, la réponse porte une mention datée (« Ticket clôturé depuis GLPI le … sans solution renseignée »), pour qu'un ticket clos ne reste jamais sans réponse. Le **type de résolution** est positionné sur « Résolu » s'il n'a pas déjà été choisi — il est obligatoire lors d'une clôture faite dans ISI-APP. Une réponse déjà saisie dans ISI-APP n'est jamais remplacée |
| Mise à la corbeille | Ticket archivé |
| **Sortie de corbeille** | Ticket de nouveau visible — uniquement si c'est la synchronisation qui l'avait archivé. Un ticket archivé par un technicien dans ISI-APP reste archivé : le connecteur ne défait pas une décision humaine |
| Changement de technicien assigné | Technicien affecté mis à jour |
| **Ajout ou retrait d'un demandeur** | Le demandeur est rattaché au ticket ISI-APP, ou son rattachement retiré |

Un commentaire **rédigé dans ISI-APP** puis transmis à GLPI n'est jamais réécrit ni retiré par
ces mécanismes : il reste tel quel dans son fil d'origine.

Aucune de ces actions n'est répercutée sur un ticket **sorti du périmètre des sujets**
(cf. [Périmètre des sujets](#périmètre-des-sujets-envoyés-vers-glpi)) : il n'est plus piloté par
GLPI.

**Non synchronisé** : les **observateurs** d'un ticket. L'option « Synchroniser les observateurs »
du paramétrage est présente mais reste sans effet à ce jour.

### Sens ISI-APP → GLPI
Le connecteur récupère les tickets ISI-APP modifiés depuis la dernière synchro. Pour chacun :
- Si lié à un ticket GLPI, il est mis à jour côté GLPI.
- Sinon, il est créé côté GLPI. **Le titre du ticket ISI-APP est alors préfixé `[GLPI#1234]`** pour permettre au support de retrouver facilement le ticket dans les deux outils.
- Les commentaires, les tâches, la solution et les pièces jointes suivent.

### Demandeur du ticket

Le demandeur d'un ticket ISI-APP est transmis à GLPI. Trois cas, dans cet ordre :

1. **un compte GLPI porte la même adresse** → il devient le demandeur du ticket GLPI ;
2. en mode utilisateur **« Par email »**, si le demandeur est un compte ISI-APP sans équivalent
   GLPI → le compte GLPI est créé, puis désigné comme demandeur ;
3. si le demandeur a été **saisi à la main** (sans compte ISI-APP) et que le mode est « Par
   email », son compte GLPI est créé également — à condition que l'adresse soit valide, une saisie
   approximative créerait un compte inutilisable dans votre GLPI ;
4. sinon → le demandeur est déclaré **sans compte** : son adresse s'affiche dans le champ Demandeur
   de GLPI, sans qu'aucun compte soit créé. C'est le mécanisme natif de GLPI pour un demandeur
   externe, celui qu'utilise son collecteur de mails. En mode « anonyme », qui interdit toute
   création de compte, c'est ce qui évite un ticket GLPI sans demandeur.

Un ticket **mis à la corbeille** dans ISI-APP n'est plus poussé vers GLPI (il pouvait s'y recréer
entièrement). La suppression n'est en revanche pas propagée à GLPI : le ticket y reste ouvert.

Un ticket ISI-APP peut aussi porter un demandeur **saisi à la main**, sans compte ni adresse (un nom
et éventuellement un téléphone, quand la demande est enregistrée pour un tiers). GLPI n'a alors nulle
part où le ranger : son identité est consignée **une seule fois en commentaire** du ticket GLPI
(« Demandeur Isi-APP : Jean Dupont — 06 12 34 56 78 »), pour que l'information ne se perde pas.

GLPI ne notifie le demandeur que si le paramètre **« Envoi des mails »** lui en donne la charge, afin
de ne pas doubler les notifications d'ISI-APP.

**Plusieurs demandeurs** peuvent être rattachés à un même ticket : ils sont tous transmis, GLPI
sachant lui aussi en porter plusieurs. Un demandeur **ajouté à la main dans GLPI**, qu'ISI-APP ne
connaît pas, est conservé : la synchronisation ne retire que les demandeurs qu'elle a elle-même
déclarés — et elle le fait quand leur adresse change (l'ancienne ne reste pas à côté de la nouvelle)
ou quand le rattachement est supprimé dans ISI-APP.

Enfin, un demandeur qu'ISI-APP a exclu de ses notifications ne sera pas notifié par GLPI non plus.

Dans l'autre sens, **tous les demandeurs d'un ticket GLPI sont rattachés au ticket ISI-APP**, y
compris ceux **sans compte** (tickets créés par le collecteur de mails, par exemple), rapprochés par
leur adresse. Auparavant, seul le premier demandeur arrivait — et un ticket GLPI ouvert avec deux
demandeurs n'en montrait qu'un dans ISI-APP, définitivement. Un demandeur retiré dans GLPI voit son
rattachement ISI-APP disparaître ; un demandeur rattaché depuis ISI-APP, lui, reste intact.

### Affectation du technicien

L'affectation circule **dans les deux sens** :

- **GLPI → ISI-APP** : le technicien assigné dans GLPI devient le technicien affecté du ticket
  ISI-APP (rapprochement par email, au sein de votre organisation). GLPI acceptant **plusieurs**
  techniciens sur un ticket alors qu'ISI-APP n'en gère qu'un, c'est le **premier assigné
  correspondant à un compte ISI-APP** qui est retenu — et non le premier de la liste GLPI, qui
  peut être un compte technique sans adresse email. À défaut de correspondance, le ticket revient
  au **technicien ISI-APP par défaut** s'il est renseigné.
- **ISI-APP → GLPI** : le technicien affecté dans ISI-APP est posé comme assigné du ticket GLPI,
  et les éventuels autres assignés sont retirés — ISI-APP n'en désignant qu'un. Le rapprochement
  se fait là aussi par email, dans cet ordre :

  1. **compte GLPI portant la même adresse** → c'est lui qui est assigné ;
  2. sinon, en mode utilisateur **« Par email »** → le compte GLPI est **créé** puis assigné ;
  3. sinon, si un **« Technicien GLPI par défaut »** est renseigné dans le paramétrage → le ticket
     lui est assigné (l'événement est journalisé en avertissement : le ticket est bien pris en
     charge, mais pas par le technicien désigné dans ISI-APP) ;
  4. sinon l'affectation n'est pas transmise, et le log indique quoi régler.

Si le ticket n'a **aucun** technicien affecté dans ISI-APP, la synchronisation ne retire pas
l'assigné éventuellement présent dans GLPI : l'absence d'affectation ne se distingue pas d'une
désaffectation volontaire, et un retrait automatique effacerait le travail fait côté GLPI.

### « Résolu » dans GLPI : clôturer ou non dans ISI-APP ?

GLPI distingue deux statuts de fin, **Résolu** (une solution est proposée) puis **Clos**. ISI-APP
n'a pas d'état intermédiaire : la résolution y qualifie une clôture. Le mapping des statuts laisse
donc le choix, pour le statut GLPI « Résolu » :

| Correspondance choisie | Effet sur le ticket ISI-APP |
|---|---|
| **Résolu sans clôture** | Le ticket est marqué **résolu** sans être clôturé : son statut ISI-APP n'est pas modifié, la réponse est reprise de la solution GLPI, et le résolveur est renseigné. Comme pour une résolution saisie dans ISI-APP, **la clôture automatique intervient 3 jours plus tard** ; le gestionnaire peut clôturer avant, et un passage de GLPI en « Clos » clôture immédiatement. **Si le ticket est réouvert entre-temps** (des deux côtés), la clôture automatique est abandonnée : elle ne vient pas refermer un ticket reparti en traitement |
| **Clôturé immédiatement** | Le ticket est clôturé sur-le-champ, avec sa réponse et son type de résolution |
| Affecté / Ouvert | La résolution GLPI n'est pas reflétée ; la solution reste visible en commentaire |

Un ancien choix « Résolu ET clôturé » subsiste dans la liste pour les instances qui l'ont déjà
enregistré : il **clôture immédiatement**, exactement comme « Clôturé ». Il est signalé comme tel
dans l'écran ; il n'y a rien à changer si votre paramétrage l'utilise et que la clôture immédiate
vous convient.

Un ticket « résolu non clôturé » est renvoyé vers GLPI comme **Résolu**, pas comme Clos : les deux
outils restent alignés sans que l'un reclôture ce que l'autre a seulement résolu.

### Clôture, réouverture et mise en attente
- **Clôture ISI-APP → GLPI** : le texte de réponse saisi à la clôture est déposé comme
  **solution** sur le ticket GLPI, qui passe ensuite en « Clos ». Sans solution, GLPI refuse la
  clôture — le connecteur la crée donc systématiquement (avec un libellé générique si aucune
  réponse n'a été saisie).
- **Solution marquée « Refusée » dans GLPI** : dans GLPI, réouvrir un ticket qui portait une
  solution équivaut à **refuser cette solution** — elle s'affiche alors « Refusée le … par … ».
  Lorsque le ticket est reclôturé depuis ISI-APP, la solution est donc **remise à l'état
  approuvé**, avec la date de la clôture : la clôture décidée dans ISI-APP vaut approbation. Sans
  cela, un ticket pourtant reclôturé continuait d'afficher la mention de refus dans GLPI.
- **Réponse de clôture modifiée** : si le ticket est reclôturé avec une réponse différente
  (typiquement après une réouverture), la solution GLPI est **mise à jour** pour refléter la
  nouvelle réponse, plutôt que de laisser l'ancienne affichée. Le ticket GLPI ne se retrouve
  jamais avec plusieurs solutions concurrentes.
  Seul cas non couvert : un ticket **déjà clos dans GLPI et sans aucune solution** n'accepte pas
  qu'on lui en ajoute une (refus de GLPI) ; la synchronisation le signale alors dans ses logs au
  lieu de laisser croire que la réponse est partie.
- **Réouverture ISI-APP → GLPI** : la **raison de réouverture** saisie dans ISI-APP est
  enregistrée en commentaire du ticket, visible dans son fil de discussion, et remonte donc
  dans GLPI comme **suivi**. Le ticket GLPI repasse par ailleurs à l'état ouvert. Le support
  retrouve ainsi *pourquoi* le ticket a été réouvert directement dans GLPI, sans avoir à
  consulter ISI-APP.
- **Mise en attente ISI-APP → GLPI** : même principe. Le ticket GLPI passe « En attente » et la
  **raison de la mise en attente** l'accompagne sous forme de suivi. Sans cela, le ticket
  changeait d'état côté GLPI sans aucun motif visible.
- **Réactivation ISI-APP → GLPI** : la reprise d'un ticket suspendu ajoute elle aussi un suivi
  (« Le ticket a été réactivé »), en rappelant l'attente qui vient d'être levée. Chaque
  changement d'état visible dans GLPI est ainsi accompagné de son explication.

### Modes utilisateur
Le champ "Mode utilisateur" contrôle comment ISI-APP traite les utilisateurs côté GLPI :

| Mode | Comportement |
|---|---|
| **Anonyme** | Aucun compte GLPI n'est créé. Si le technicien affecté dans ISI-APP n'a pas de compte GLPI portant la même adresse email, l'affectation ne peut pas être transmise et la synchronisation le signale dans ses logs |
| **Par email** | Recherche du compte GLPI par email et **le crée s'il est absent**, au moment où un utilisateur ISI-APP doit réellement être référencé dans GLPI (et non en déversant tout l'annuaire) |
| **Reprise manuelle** | Utilise uniquement les correspondances déjà saisies, ne crée jamais de compte |

> Le mode **Par email** crée de véritables comptes dans le GLPI du client (login = partie gauche
> de l'adresse, nom et prénom repris d'ISI-APP, compte actif). C'est la contrepartie d'une
> affectation qui « passe » toujours : à choisir en connaissance de cause, notamment si les
> comptes GLPI sont soumis à licence ou provisionnés depuis un annuaire.

#### Rapprochement des utilisateurs GLPI avec les comptes ISI-APP

Dans le sens **GLPI → ISI-APP**, les utilisateurs GLPI (demandeur, technicien affecté, auteur
d'un suivi, auteur de la solution) sont rapprochés des comptes ISI-APP **par email, au sein de
votre organisation uniquement**.

Un email présent dans GLPI mais rattaché à un compte d'une **autre** organisation n'est jamais
utilisé : c'est fréquent, par exemple pour les techniciens de l'éditeur présents dans votre
GLPI. Le ticket est alors affecté au **technicien par défaut** de l'instance (s'il est
renseigné, et lui aussi doit appartenir à votre organisation) ou laissé non affecté, plutôt que
d'attribuer le ticket à une personne extérieure.

Conséquence pratique : pour qu'un technicien GLPI soit reconnu, son email doit correspondre à un
compte ISI-APP de votre organisation.

### Périmètre des sujets envoyés vers GLPI

Le paramétrage permet de restreindre la synchronisation ISI-APP → GLPI à certains **sujets** de
ticket (champ « Sujets à envoyer vers GLPI » ; laissé vide, tous les sujets partent). Un ticket
dont le sujet n'est pas dans cette liste n'est jamais poussé vers GLPI.

**Requalifier un ticket** (changer son sujet) est une action courante : une demande arrivée en
« Connexions Internet — Wi-Fi » se révèle être un achat de matériel, et passe en « Achats », sujet
hors périmètre. Deux comportements en découlent :

- **Le nouveau sujet est conservé.** La synchronisation ne remet plus le ticket dans la catégorie
  qu'il porte côté GLPI. Auparavant, la requalification était annulée au cycle suivant : le sujet
  d'origine revenait, et le ticket ne pouvait donc jamais sortir du périmètre.
- **Le ticket GLPI est soldé**, si l'option « Clôturer dans GLPI les tickets sortis du périmètre »
  est activée. Le ticket GLPI reçoit un suivi et une solution expliquant la sortie de périmètre
  (« son sujet est désormais « Achats », qui n'est pas synchronisé avec GLPI. Le suivi se poursuit
  dans Isi-APP »), puis passe au statut correspondant à « Clôturé » dans les correspondances de
  statuts. Sans cette option, le ticket reste **ouvert indéfiniment** dans GLPI, alors que plus
  aucune information ne lui parviendra.

Une fois soldé, le ticket est **détaché** de la synchronisation : les actions faites côté GLPI ne
redescendent plus dans ISI-APP — en particulier, la clôture qui vient d'être posée dans GLPI ne
clôture pas le ticket ISI-APP, qui poursuit sa vie sous son nouveau sujet. Le lien entre les deux
tickets n'est pas détruit pour autant : si le sujet **revient dans le périmètre**, la
synchronisation reprend au cycle suivant et rouvre le ticket GLPI selon l'état ISI-APP.

L'option est **désactivée par défaut**, y compris sur les instances existantes : l'activer clôture,
au cycle suivant, tous les tickets déjà sortis du périmètre. C'est en général l'effet recherché,
mais il vaut mieux le déclencher en connaissance de cause. Une solution GLPI déjà enregistrée n'est
jamais remplacée par le motif de sortie de périmètre, sauf si elle a été **refusée** (une
réouverture vaut refus dans GLPI) — le ticket se fermerait sinon sur une réponse invalidée.

### Tâches

Les **tâches** d'un ticket circulent dans les deux sens : une tâche créée dans GLPI apparaît sur le
ticket ISI-APP, une tâche créée dans ISI-APP apparaît sur le ticket GLPI. Les modifications
suivent, et une tâche supprimée d'un côté disparaît de l'autre.

Les deux outils ne décrivent pas une tâche de la même façon ; voici ce que devient chaque
information :

| Information | GLPI | ISI-APP |
|---|---|---|
| Intitulé | GLPI n'a **pas de titre** : sa tâche est un simple texte | Le titre ISI-APP ouvre le texte GLPI ; à l'inverse, la première ligne du texte GLPI devient le titre ISI-APP et la suite la description |
| Avancement | « À faire » / « Terminée » | « Terminée » ↔ **100 %** avec sa date de réalisation. Les valeurs intermédiaires (10 %, 50 %…) n'ont pas d'équivalent GLPI : elles sont conservées telles quelles tant que GLPI ne dit pas « terminée » |
| Dates | Début et fin planifiés | Début ↔ début, fin planifiée ↔ **échéance**. La fenêtre n'est transmise à GLPI que si le début **et** l'échéance sont renseignés, GLPI refusant une fin antérieure au début |
| Intervenant | Technicien de la tâche | Rapproché **par email** au sein de votre organisation, comme pour l'affectation d'un ticket. Sans correspondance, le technicien ISI-APP par défaut prend le relais ; côté GLPI, la tâche part sans technicien plutôt que de ne pas partir |
| Visibilité | Tâche privée | Visibilité « Privée » |
| Priorité | absente des tâches GLPI | « Normale » à l'import, jamais réécrite ensuite |
| Durée | Temps passé (heures) | Jours estimés. Les deux ne mesurent pas la même chose : **ce champ n'est pas synchronisé** |

Deux comportements à connaître :

- **La synchronisation ne notifie personne.** Une tâche qui arrive de GLPI n'envoie pas le mail
  d'affectation ISI-APP : le connecteur reflète un état, il ne rejoue pas une action humaine, et
  les notifications GLPI existent déjà de leur côté.
- **Une tâche supprimée dans GLPI est retirée du ticket ISI-APP**, sans être effacée (le même
  principe que pour les commentaires). Une tâche supprimée dans ISI-APP est, elle, **supprimée dans
  GLPI**. En revanche, une tâche seulement détachée du ticket côté ISI-APP tout en continuant
  d'exister est conservée dans GLPI : le signal est trop ambigu pour effacer une donnée chez vous.

### Pièces jointes

Documents et images circulent dans les deux sens, en même temps que le ticket qui les porte. Un
fichier n'est transmis qu'une fois : il ne revient jamais en second exemplaire du côté d'où il
part.

Deux limites propres à GLPI méritent d'être connues :

- **Le titre d'un document ISI-APP n'est pas son nom de fichier.** GLPI n'accepte un fichier que
  s'il reconnaît son extension. Le connecteur transmet donc le fichier sous son nom réel
  (« Politique de sécurité**.pdf** ») tout en conservant le titre saisi dans ISI-APP comme intitulé
  du document. Auparavant, un document dont le titre ne portait pas d'extension arrivait dans GLPI
  **vide** : le ticket affichait une pièce jointe sans nom ni fichier téléchargeable.
- **Un type de fichier refusé par GLPI est signalé.** Si l'extension ne fait pas partie des types
  autorisés dans le GLPI du client (paramétrage GLPI, « Types de documents »), la pièce jointe
  n'est pas transmise et la synchronisation l'écrit dans son journal, avec le motif renvoyé par
  GLPI. Rien n'est laissé derrière côté GLPI.

Dans l'autre sens, la **taille** d'une pièce jointe importée de GLPI est mesurée sur le fichier
reçu. Les pièces jointes importées avant cette correction, affichées « 0 Ko », voient leur taille
rétablie automatiquement au passage suivant de la synchronisation — le fichier lui-même, lui, avait
toujours été correctement téléchargé.

Enfin, un document présent dans GLPI **sans fichier associé** (résidu des envois défectueux
décrits ci-dessus) est signalé dans le journal et non importé : il n'y a rien à récupérer. Ces
documents vides peuvent être supprimés dans GLPI.

### Politique d'envoi des mails
Pour éviter qu'un même événement génère **deux notifications** (une par ISI, une par GLPI), le client choisit qui envoie : `ISI` ou `GLPI`. La partie qui n'envoie pas doit avoir ses notifications désactivées pour les tickets synchronisés. À documenter dans le guide utilisateur du client.

### Périmètre exclu
Pour limiter la complexité, **ne sont pas synchronisés** :
- Les **demandes de validation** (`ITILValidation`)
- Les **observateurs** d'un ticket (l'option de paramétrage existe mais reste sans effet)

Toute extension du périmètre doit faire l'objet d'une nouvelle évolution.

### Robustesse
Chaque ticket est traité indépendamment : une erreur sur un ticket est journalisée dans les logs et n'arrête pas la synchronisation des autres. La synchronisation est **toujours asynchrone** — il n'y a pas de mode "temps réel" qui répliquerait instantanément chaque action.

## Cycle de synchronisation automatique

Selon la fréquence choisie dans le paramétrage, une commande Artisan (`glpi:sync`) tourne toutes les 5, 10, 20 ou 60 minutes via le scheduler. Elle parcourt toutes les instances GLPI actives et synchronise chacune indépendamment. La dernière date de synchro est mise à jour à la fois sur la `StoreInstance` (visible dans la card de l'index) et dans le paramétrage.

Si la fréquence est sur **Manuel (0)**, seule l'action via le bouton "Synchroniser maintenant" déclenche une sync.

### Dates du ticket et synchronisation

La synchronisation **ne modifie jamais la date de dernière modification** du ticket (colonne
« Dernière modif. » des listes) : celle-ci ne bouge que sur une action faite dans ISI-APP —
commentaire, affectation, changement de sujet, clôture… Les changements importés de GLPI sont bien
appliqués au ticket, mais sans repousser cette date, qui reste ainsi un indicateur d'activité
humaine exploitable pour le tri et le suivi.

La **date de prise en charge** suit la même logique : elle est posée à la première affectation, ou
lors d'un changement de technicien, et n'est plus réécrite par les cycles suivants. C'est cette
date qui sert au calcul du **temps de prise en charge** et du **temps de résolution** — les cycles
de synchronisation ne faussent donc plus ces indicateurs.

### Conservation des journaux de synchronisation

Les journaux affichés dans l'onglet dédié sont **conservés 30 jours**, puis supprimés
automatiquement chaque nuit. Chaque cycle écrivant une ligne par objet traité, sans cette purge
la table grossit indéfiniment (elle avait atteint plus de 250 000 lignes) et ralentit l'affichage
de la page du connecteur. Les journaux servent au diagnostic à chaud ; pour conserver la trace
d'un incident plus ancien, il faut l'exporter ou le recopier avant expiration.

## Sécurité

- **Tokens chiffrés** côté base de données via `encrypt()` Laravel — jamais stockés en clair, jamais retournés dans les vues, jamais loggés.
- **HTTPS obligatoire** pour l'URL API GLPI — les URLs HTTP sont rejetées au moment de la sauvegarde.
- **Multi-tenancy strict** : chaque méthode du contrôleur vérifie que l'instance appartient bien à l'entité de l'utilisateur connecté (`session('user.info._id')`).
- **Champs token toujours vides à l'affichage** — l'utilisateur saisit à nouveau s'il veut modifier, sinon les tokens existants sont préservés.

## Limitations connues / points d'attention pour l'utilisateur

- Une **panne du serveur GLPI** ou un changement de tokens entraîne l'échec silencieux des synchronisations suivantes. Le badge de statut sur l'onglet "Synchronisation" et les logs permettent de le détecter.
- Les **pièces jointes** très volumineuses peuvent allonger fortement le temps de synchro.
- Les **modifications concurrentes** d'un même ticket des deux côtés entre deux syncs résultent en un écrasement par la version la plus récente — pas de fusion automatique.
- Si le client change la **catégorisation** de son GLPI sans mettre à jour la table de correspondance, les nouveaux tickets ISI-APP retombent dans la catégorie par défaut et un avertissement est journalisé.

## Liens utiles

- Vue d'ensemble du Store : `docs/store/store-connectors-spec.md`
- Connecteur OCS Inventory (modèle de référence) : `docs/store/store-connectors-spec.md`
- Documentation officielle API REST GLPI : https://glpi-project.org/fr/documentation/

> Doc technique : [.claude/technical-docs/store/connecteur_glpi.md](../../.claude/technical-docs/store/connecteur_glpi.md)
