chore(ideai): clôture de #65 et ouverture de #71 (diagnostic d'accessibilité)

État `.ideai/` indépendant des branches de feature, committé directement sur
`develop` (précédents `2fa226e`, `56757c7`).

- #65 « serveur headless idea-serve » passé en `closed` par Main : mergé dans
  `develop` via `fe0e53e`, vert, branche supprimée.
- #71 « diagnostic d'accessibilité du serveur » ouvert, lié à #68 et #65.
- Journal des tâches de fond : complétions enregistrées.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 18:11:38 +02:00
parent 32c670a2b3
commit 56b9f5f619
7 changed files with 195 additions and 10 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,8 @@
---
issueRef: "#65"
version: 6
version: 7
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1784202758668
updatedAt: 1784210420516
---
# Ticket #65 — Serveur headless `idea-serve` (carnet de chantier)

View File

@ -2,7 +2,7 @@
id: "f9f7067b-92b7-4737-ad99-4487ad8c8b13"
number: 65
title: "Serveur headless : extraire idea-serve du binaire Tauri (cœur partagé)"
status: "qa"
status: "closed"
priority: "high"
sprint: "028179b1-eaf4-41e9-9c1f-7c37125117e6"
links: [{"target":"#13","kind":"dependsOn"}]
@ -10,8 +10,8 @@ agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784187583229
updatedAt: 1784202758668
version: 6
updatedAt: 1784210420516
version: 7
---
Objectif : produire un binaire serveur headless (`idea-serve`) SANS dépendance Tauri/WebKit, bâti sur le même cœur backend que le desktop (pas de fork). Prérequis de l'image Docker serveur/client. Cadré par Architect (suite #13).

View File

@ -0,0 +1,6 @@
---
issueRef: "#71"
version: 1
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1784210443885
---

View File

@ -0,0 +1,39 @@
---
id: "4d78a0e9-b54c-4db6-92e5-1461c17d7c84"
number: 71
title: "Diagnostic d'accessibilité du serveur : dire pourquoi ça ne marche pas, pas seulement que ça tourne"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#68","kind":"relatesTo"},{"target":"#65","kind":"relatesTo"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784210443885
updatedAt: 1784210443885
version: 1
---
Issu d'une session de debug live réelle (2026-07-16) où un serveur `idea-serve` CORRECTEMENT configuré est resté injoignable, sans que rien dans le produit n'indique pourquoi. Le serveur tournait, se croyait bon, affichait « listening on … ». Deux boucles de debug successives ont été nécessaires, dont aucune n'était diagnosticable depuis le produit.
**Problème de fond : l'échec est invisible.** Un serveur peut être parfaitement configuré et totalement inatteignable ; aujourd'hui la seule façon de le savoir est de sortir du produit (curl, ss, ufw, dig).
Les trois échecs réels rencontrés, tous silencieux :
1. **Bind loopback + reverse proxy sur une autre machine** → le proxy ouvre une connexion vers *sa propre* loopback, la requête n'arrive jamais. Aucun message, juste un timeout côté navigateur. Aggravé par `docs/server-client-mode-remote.md`, dont l'exemple du cas distant utilise `--listen 127.0.0.1:17373` en supposant sans le dire que le proxy est co-localisé (correction doc traitée à part).
2. **Pare-feu hôte (ufw actif, port non ouvert)** → dissymétrie caractéristique : joignable depuis la machine locale, timeout depuis toute autre machine. Rien ne le signale.
3. **Origine non conforme → 403 muet**`--public-origin` compare en ÉGALITÉ STRICTE. Ouvrir l'UI par l'IP (`http://192.168.1.75:17373`) au lieu du nom de domaine donne un 403 sur toute l'API, sans explication dans l'UI. C'est le piège n°1 pour un nouvel utilisateur.
**Périmètre proposé (à cadrer par Architect).**
**Lot 1 — Surfacer les origines rejetées. Meilleur rapport valeur/coût : l'événement EXISTE déjà.** `SecurityLogEvent::OriginRejected { origin, route }` dans `crates/web-server/src/lib.rs` est aujourd'hui simplement `eprintln!` sur stderr — donc invisible en desktop, et invisible en Docker sans aller lire les logs. L'exposer (DTO + surface UI) transforme le mystère en diagnostic d'une ligne : « un client s'est connecté depuis `http://192.168.1.75:17373`, or l'origine autorisée est `https://idea.anthonybouteiller.ovh` ». Attention : c'est un log de sécurité, borner la rétention et ne pas en faire un canal de fuite d'information.
**Lot 2 — Dire quand le serveur est JOIGNABLE, pas seulement qu'il tourne.** Le serveur ne peut pas se tester depuis l'extérieur, mais il peut détecter ce qui rend l'échec certain :
- pare-feu hôte actif dont le port d'écoute n'est pas autorisé (ufw/firewalld) ;
- `public_origin` dont le DNS ne résout vers aucune interface locale ⇒ indice fort que le proxy est ailleurs, donc qu'un bind loopback ne peut pas marcher ;
- afficher l'upstream exact à coller dans la config du proxy (`http://192.168.1.75:17373`) plutôt que de le laisser deviner.
Ces détections sont des heuristiques : elles doivent INFORMER, jamais bloquer le démarrage.
**Hors périmètre :** le choix du mode par intention (« proxy sur cette machine » vs « sur une autre machine ») appartient à F2 de #68 — c'est le panneau desktop, ça ne change aucun contrat backend.
**Attention frontière :** les lots ci-dessus doivent servir AUSSI le mode headless/Docker (`idea-serve` sans desktop), pas seulement le panneau desktop. Le diagnostic ne doit pas naître prisonnier de l'UI Tauri.

View File

@ -1,3 +1,3 @@
{
"nextNumber": 71
"nextNumber": 72
}

View File

@ -677,11 +677,11 @@
"issueRef": "#65",
"path": "65",
"title": "Serveur headless : extraire idea-serve du binaire Tauri (cœur partagé)",
"status": "qa",
"status": "closed",
"priority": "high",
"sprint": "028179b1-eaf4-41e9-9c1f-7c37125117e6",
"assignedAgentIds": [],
"updatedAt": 1784202758668
"updatedAt": 1784210420516
},
{
"issueRef": "#66",
@ -738,6 +738,16 @@
"a6ced819-b893-4213-b003-9e9dc79b9641"
],
"updatedAt": 1784194049447
},
{
"issueRef": "#71",
"path": "71",
"title": "Diagnostic d'accessibilité du serveur : dire pourquoi ça ne marche pas, pas seulement que ça tourne",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [],
"updatedAt": 1784210443885
}
]
}