# Format JSON du spooler tickets (projects//data/issues/) Les mails et réponses sont stockés dans **projects//data/issues/** (sous ia_dev, par projet). Filtrage par **expéditeurs autorisés** (conf.json → `tickets.authorized_emails`), sans s’appuyer sur le statut « non lu ». Le traitement se base uniquement sur le **statut des issues** ; aucun enregistrement n’est supprimé. ## Emplacement et nommage des fichiers - **Racine** : `ia_dev/projects//data/issues/` (id = slug projet, ex. contenu de `ai_project_id` ou `.ia_project` à la racine du dépôt) - **Messages entrants** : `__.` (le `_` assure l’unicité par message IMAP) - `date` : `YYYY-MM-DDTHHmmss` (ex. `2026-03-14T094530`) - `from_sanitized` : adresse expéditeur rendue sûre pour le système de fichiers (ex. `user_example.com` pour `user@example.com` : `@` → `_`, caractères interdits remplacés ou supprimés) - `uid` : UID IMAP (évite les doublons pour un même expéditeur à la même seconde) - `status` : `pending` | `inprogress` | `done` - **Réponses envoyées** : `_.response` (même base de nom que le message entrant associé, extension `.response`) - **Pièces jointes (pj)** : pour un message entrant de base `` (ex. `2026-03-14T094530_laurence_lecoffre.io_42`), les pièces jointes sont dans le répertoire **`.d/`** (ex. `2026-03-14T094530_laurence_lecoffre.io_42.d/`). Nommage des fichiers : `_` (ex. `0_document.pdf`, `1_capture.png`). Le JSON du message contient le tableau `attachments` avec pour chaque entrée le chemin relatif à `data/issues/`, le type MIME et la taille pour que l’agent qui traite les tickets puisse les utiliser. Exemples : - `2026-03-14T094530_laurence_lecoffre.io.pending` — message entrant en attente - `2026-03-14T094530_laurence_lecoffre.io.inprogress` — en cours de traitement - `2026-03-14T094530_laurence_lecoffre.io.done` — traité - `2026-03-14T101200_laurence_lecoffre.io.response` — réponse envoyée ## Schéma JSON — message entrant (incoming) Fichiers `.pending`, `.inprogress`, `.done`. ```json { "version": 1, "type": "incoming", "message_id": "", "from": "laurence@lecoffre.io", "to": ["ai.support.lecoffreio@4nkweb.com"], "subject": "Demande d'information", "date": "Fri, 14 Mar 2026 09:45:30 +0100", "body": "Texte brut du corps du mail.", "references": ["", ""], "in_reply_to": "", "uid": "42", "created_at": "2026-03-14T09:45:35Z", "issue_number": null, "status": "pending", "attachments": [ { "filename": "document.pdf", "path": "2026-03-14T094530_laurence_lecoffre.io_42.d/0_document.pdf", "content_type": "application/pdf", "size": 12345 }, { "filename": "capture.png", "path": "2026-03-14T094530_laurence_lecoffre.io_42.d/1_capture.png", "content_type": "image/png", "size": 6789 } ] } ``` | Champ | Type | Description | |-------|------|-------------| | `version` | number | Version du schéma (1) | | `type` | string | `"incoming"` | | `message_id` | string | En-tête Message-ID du mail | | `from` | string | Adresse de l’expéditeur | | `to` | string[] | Adresses destinataires | | `subject` | string | Sujet | | `date` | string | Date d’envoi (RFC2822 ou ISO8601) | | `body` | string | Corps du message (texte brut) | | `references` | string[] | En-tête References (liste de Message-IDs) | | `in_reply_to` | string \| null | En-tête In-Reply-To | | `uid` | string | UID IMAP (pour référence, pas pour marquer lu) | | `created_at` | string | Date d’écriture dans le spool (ISO8601) | | `issue_number` | number \| null | Numéro d’issue Gitea si une issue a été créée | | `status` | string | `pending` \| `inprogress` \| `done` | | `attachments` | array | Pièces jointes : tableau d’objets (voir ci-dessous). `path` est relatif à `data/issues/` ; les fichiers sont dans `.d/`. L’agent qui traite les tickets peut les lire depuis `projects//data/issues/`. | **Objet pièce jointe** : `filename` (nom d’origine), `path` (chemin relatif sous `projects//data/issues/`), `content_type` (MIME), `size` (octets). ## Schéma JSON — réponse envoyée (response) Fichiers `.response`. ```json { "version": 1, "type": "response", "in_reply_to_message_id": "", "to": "laurence@lecoffre.io", "subject": "Re: Demande d'information", "body": "Texte de la réponse envoyée par l'agent.", "sent_at": "2026-03-14T10:12:00Z", "created_at": "2026-03-14T10:12:00Z" } ``` | Champ | Type | Description | |-------|------|-------------| | `version` | number | Version du schéma (1) | | `type` | string | `"response"` | | `in_reply_to_message_id` | string | Message-ID du mail auquel on répond | | `to` | string | Destinataire de la réponse | | `subject` | string | Sujet de la réponse (ex. Re: …) | | `body` | string | Corps de la réponse envoyée | | `sent_at` | string | Date d’envoi (ISO8601) | | `created_at` | string | Date de création du fichier (ISO8601) | ## Configuration projet (conf.json) - **ticketing_url** et la config ticketing sont sous la clé **`tickets`** (et non plus sous `git`). - **`tickets`** contient : - `ticketing_url` : URL des issues Gitea - `authorized_emails` : - **`to`** : récupérer **uniquement** les mails **envoyés à** cette adresse (destinataire). - **`from`** : récupérer **uniquement** les mails **envoyés par** ces adresses (expéditeurs autorisés). Exemple : ```json "tickets": { "ticketing_url": "https://git.4nkweb.com/4nk/lecoffre_ng/issues", "authorized_emails": { "to": "ai.support.lecoffreio@4nkweb.com", "from": ["ai.support.lecoffreio@4nkweb.com", "laurence@lecoffre.io"] } } ``` La récupération ne prend que les messages **envoyés à** `authorized_emails.to` **et** **expédités par** une des adresses de `authorized_emails.from`. Aucun marquage « lu / non lu » ; aucun enregistrement du spool n’est supprimé.