chore(ideai): ouverture de #73 (TLS intégré à idea-serve)
#73 ouvert en priorité haute : intégrer TLS à `idea-serve` pour supprimer la cause racine de la cérémonie reverse proxy, dont #72 vient de durcir les garde-fous. Lié à #72, #66, #68 et #71. État `.ideai/` indépendant du code de #72, committé directement sur `develop`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
6
.ideai/tickets/73/carnet.md
Normal file
6
.ideai/tickets/73/carnet.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
issueRef: "#73"
|
||||
version: 1
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1784223044517
|
||||
---
|
||||
46
.ideai/tickets/73/issue.md
Normal file
46
.ideai/tickets/73/issue.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
id: "a43a07d0-573f-41e9-9b7b-2f88beb4e660"
|
||||
number: 73
|
||||
title: "TLS intégré à idea-serve : supprimer la cause racine de la cérémonie reverse proxy"
|
||||
status: "open"
|
||||
priority: "high"
|
||||
sprint: null
|
||||
links: [{"target":"#72","kind":"relatesTo"},{"target":"#66","kind":"relatesTo"},{"target":"#68","kind":"relatesTo"},{"target":"#71","kind":"relatesTo"}]
|
||||
agentRefs: []
|
||||
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
createdAt: 1784223044517
|
||||
updatedAt: 1784223044517
|
||||
version: 1
|
||||
---
|
||||
**Décision utilisateur (2026-07-16) : IdeA gagne le TLS intégré.** Contrainte posée : prendre la technologie la plus légère.
|
||||
|
||||
**La cause racine, établie par une session de debug réelle.** Un utilisateur a mis une matinée à exposer `idea-serve` derrière son nginx. Cinq obstacles, découverts un par un en tapant dans le mur : bind loopback injoignable par un proxy distant (timeout muet), ufw (timeout muet), `--trusted-proxy` obligatoire (#72), `X-Forwarded-Proto` absent (403), `X-Forwarded-Host` absent (403).
|
||||
|
||||
**Ces cinq obstacles ont UNE cause : le serveur ne sait pas chiffrer.** Ne pouvant pas terminer le TLS, il doit *croire quelqu'un d'autre sur parole* quand on lui dit que la connexion publique était en HTTPS. `--trusted-proxy` sert à savoir qui a le droit de lui mentir ; `X-Forwarded-Proto` est le mensonge lui-même. Toute la machinerie de #72 n'existe **que** parce qu'il manque cette capacité. #66 avait acté l'exclusion noir sur blanc (« Pas de TLS applicatif V1 », « Hors périmètre V1 : TLS intégré ») — c'est cette ligne qui a produit les cinq obstacles.
|
||||
|
||||
**Ce que le TLS intégré change.** L'utilisateur ouvre le 443 de son routeur, donne son domaine, terminé : pas de `--trusted-proxy`, pas de `X-Forwarded-*`, pas de proxy du tout. Un reverse proxy devant reste possible, mais devient un **choix**, plus une obligation structurelle. Une bonne partie de #72 se simplifie mécaniquement — sans disparaître : le mode « derrière proxy » reste supporté et garde ses contrôles.
|
||||
|
||||
**Constat technique qui répond à la contrainte de légèreté (vérifié dans `Cargo.lock`) :**
|
||||
- `rustls` 0.23, `tokio-rustls`, `ring`, `webpki-roots`, `hyper-rustls` sont **DÉJÀ** dans l'arbre de dépendances.
|
||||
- **Aucun** `openssl`, `openssl-sys` ni `native-tls`.
|
||||
- Le coût marginal d'un TLS serveur est donc quasi nul : la brique est déjà vendue avec le projet. Pas de nouvelle chaîne de dépendances, pas de dépendance système (contrairement à OpenSSL).
|
||||
|
||||
**Pistes ACME à arbitrer par Architect :**
|
||||
- `rustls-acme` — bâti sur rustls/tokio, fournit le resolver de certificats et le renouvellement automatique. Plus intégré, moins de code à écrire.
|
||||
- `instant-acme` — plus bas niveau, pure Rust, minimal ; le challenge et le stockage restent à notre charge.
|
||||
- **Argument fort pour le challenge TLS-ALPN-01 : il ne nécessite QUE le port 443.** Pas de port 80, pas de web root séparé pour HTTP-01. Cohérent avec « l'utilisateur ouvre un port ».
|
||||
|
||||
**Limites à assumer et à documenter (ne pas vendre du rêve) :**
|
||||
- ACME exige un **domaine public** et un port joignable depuis l'extérieur. Couvre l'exposition Internet, **pas** le LAN pur sans domaine.
|
||||
- LAN pur ⇒ certificat auto-signé ⇒ avertissement navigateur. À traiter comme un mode distinct, pas à masquer.
|
||||
- IdeA devient **responsable des certificats** : stockage, permissions, renouvellement, gestion des rate limits Let's Encrypt (utiliser l'environnement de staging en test, sous peine de blocage).
|
||||
- Ne jamais mettre de certificat/clé dans un dossier synchronisé ou versionné.
|
||||
|
||||
**Interactions à cadrer :**
|
||||
- **#72** : le mode « TLS direct » ne doit exiger ni `--trusted-proxy` ni `X-Forwarded-*` — le serveur SAIT que la connexion est HTTPS puisqu'il la termine. Le mode « derrière proxy » garde ses contrôles.
|
||||
- **#66 (Docker)** : son défaut `--listen 0.0.0.0:17373` + distant est **déjà invalide** depuis #72 (refusé au démarrage sans `--trusted-proxy`). Le TLS intégré rouvre la question de l'image : proxy embarqué ou TLS applicatif ?
|
||||
- **#68** : les modes d'exposition du panneau desktop gagnent un mode « TLS direct », et le champ « IP du proxy autorisé » disparaît dans ce mode.
|
||||
- **#71** : les diagnostics doivent couvrir les échecs ACME (challenge, DNS, port 443 injoignable), qui seront la nouvelle classe d'échec silencieux.
|
||||
|
||||
**Exigence produit transverse, issue du même incident :** l'échec ne doit jamais être muet. Un certificat qui ne s'obtient pas doit le dire, avec la raison et l'action. C'est exactement le défaut qu'on corrige partout ailleurs dans ce sprint (#71).
|
||||
Reference in New Issue
Block a user