> ⛔ **NE PAS COMMITER CE FICHIER TANT QUE LA MIGRATION HTTPS N'EST PAS EN PLACE ET VALIDÉE.**
> C'est un plan de travail / aide-mémoire avec des éléments d'infra (domaines, IP, ports). On le supprime ou on le déplace hors du dépôt une fois la bascule faite.

# Migration HTTP → HTTPS de l'agent PhotoSync

> But : servir l'agent en **HTTPS** (TLS) au lieu du HTTP clair actuel. Motivé surtout par le **portage iOS** (App Transport Security bloque le HTTP clair, surtout via VPN/Tailscale — cf. [IOS-MIGRATION.md](IOS-MIGRATION.md)) et par une meilleure hygiène réseau.

---

## 1. Pourquoi le HTTP clair a été mis en place au départ (et pourquoi c'était OK)

Ce n'était pas un oubli, c'était un choix justifié au moment du build Android :

1. **Pas de nom de domaine, pas de certificat.** L'agent tourne sur une IP privée (`192.168.1.136`) ou VPN (`100.x` / `10.8.0.x`). On ne peut **pas** obtenir de certificat public Let's Encrypt pour une IP privée sans domaine → il aurait fallu un **certificat auto-signé**, que chaque client doit accepter manuellement (friction).
2. **Le trafic est déjà chiffré au niveau du tunnel.** Hors du domicile, tout passe par **Tailscale/WireGuard**, qui chiffrent **de bout en bout** (WireGuard). Le HTTP « en clair » circule donc **dans** un tunnel chiffré → pas exposé sur internet. Sur le LAN domestique, le risque est faible.
3. **Android rend ça trivial.** Il suffit de `usesCleartextTraffic: true` ([mobile/app.json](mobile/app.json#L63)) pour autoriser le HTTP. Pas de friction côté app.
4. **L'agent est volontairement minimal.** C'est un `http.createServer` Node pur ([pi-agent/src/server.js](pi-agent/src/server.js#L608)), sans Express ni dépendance. Ajouter TLS + renouvellement de certificats aurait alourdi un composant qu'on voulait simple et robuste sur un Pi armv7l.
5. **L'authentification ne dépend pas de TLS** : un **token** à temps constant protège déjà chaque endpoint ([server.js](pi-agent/src/server.js#L197-L213)). Le token, lui, ne voyage en clair que dans le tunnel chiffré.

➡️ **Bilan : en HTTP + tunnel chiffré, le modèle Android était cohérent et sûr.** Le HTTP clair n'était un problème ni de confidentialité (tunnel) ni d'auth (token).

## 2. Pourquoi il faut passer à HTTPS maintenant

- **iOS / ATS** : iOS **bloque le HTTP clair par défaut**. L'exception « réseau local » (`NSAllowsLocalNetworking`) couvre le LAN privé, **mais PAS** les IP Tailscale (`100.64.0.0/10`, plage CGNAT). En accès distant via Tailscale, l'app iOS ne pourrait **pas** joindre l'agent en HTTP sans une exception ATS large (`NSAllowsArbitraryLoads`), mal vue à la **review App Store**.
- **Review App Store** : un agent en HTTPS supprime le besoin d'exceptions ATS → dossier de review beaucoup plus propre (cf. [IOS-MIGRATION.md](IOS-MIGRATION.md) §8).
- **Défense en profondeur** : même sur le LAN, TLS protège si le tunnel n'est pas actif (même WiFi) ou contre un appareil compromis sur le réseau local.

➡️ **HTTPS devient la voie recommandée** dès qu'iOS + App Store entrent en jeu.

---

## 3. Les trois options de mise en œuvre

| Option | Effort | Certificat | Recommandé pour |
|---|---|---|---|
| **A. Reverse proxy Caddy** devant l'agent | 🟢 Faible | Auto (Let's Encrypt **ou** interne) | **Recommandé** — TLS sans toucher l'agent |
| **B. TLS natif dans l'agent** (`https.createServer`) | 🟠 Moyen | À fournir/renouveler soi-même | Si on veut zéro composant en plus |
| **C. Certificat auto-signé + pinning** | 🔴 Élevé | Auto-signé, à approuver sur chaque appareil | À éviter (friction iOS, profils à installer) |

> **Recommandation : Option A (Caddy).** Caddy obtient et **renouvelle automatiquement** les certificats, termine le TLS, et relaie en HTTP local vers l'agent **sans modifier une ligne de [server.js](pi-agent/src/server.js)**. C'est le meilleur rapport effort/robustesse, surtout sur un Pi.

---

## 4. Le vrai prérequis : un **nom de domaine** (le nœud du problème)

Let's Encrypt ne signe **que des noms de domaine**, jamais des IP privées. Il faut donc un nom qui résolve vers l'agent. Trois façons :

1. **Domaine public + DNS-01** (recommandé) : un domaine (même un sous-domaine, ex. `nas.taaazzz-prog.fr`) ; Caddy obtient le certificat via le **challenge DNS-01** (pas besoin d'exposer le port 80/443 sur internet — idéal pour un service qui ne vit que derrière le VPN). Le domaine peut pointer vers l'IP **VPN** de l'agent.
2. **Magic DNS Tailscale + `tailscale cert`** : si on reste sur Tailscale, il fournit des noms `*.ts.net` et **des certificats TLS valides** pour ces noms (`tailscale cert`). → HTTPS valide **sans domaine à soi**, parfait tant qu'on est sur Tailscale. ⚠️ Lié à Tailscale (à reconsidérer si migration WireGuard).
3. **CA interne + certificat installé** : générer sa propre autorité, l'installer comme profil de confiance sur l'iPhone. Fonctionne hors-ligne mais = **profil à installer sur chaque appareil** → friction, et complique la review App Store (le serveur de démo doit avoir un certificat **publiquement** valide). À réserver à un usage strictement perso.

➡️ **Le choix du domaine dépend de l'accès distant** : sur Tailscale → option 2 (le plus simple) ; en visant WireGuard + App Store → option 1 (domaine + DNS-01).

---

## 5. Procédure — Option A (Caddy) + domaine (DNS-01)

### 5.1 Côté serveur (hôte de l'agent)
- [ ] Posséder un **domaine** et accès à son **API DNS** (OVH, Cloudflare…) pour le challenge DNS-01.
- [ ] Faire pointer un sous-domaine vers l'IP **où l'app joindra l'agent** (IP VPN, p.ex. l'IP Tailscale/WireGuard du Pi).
- [ ] Installer **Caddy** (avec le plugin DNS du registrar, p.ex. `caddy-dns/ovh`).
- [ ] `Caddyfile` minimal :
  ```caddyfile
  nas.exemple.fr {
      tls {
          dns ovh {env.OVH_ENDPOINT} {env.OVH_APP_KEY} {env.OVH_APP_SECRET} {env.OVH_CONSUMER_KEY}
      }
      reverse_proxy localhost:8080   # l'agent reste en HTTP, en local seulement
  }
  ```
- [ ] **Restreindre l'agent au localhost** : faire écouter `server.listen(PORT, '127.0.0.1')` pour que l'agent ne soit **plus** joignable directement en HTTP — seul Caddy l'atteint. (Petit changement dans [server.js](pi-agent/src/server.js#L1480), à garder configurable par variable d'env pour ne pas casser l'install Android existante.)
- [ ] Lancer Caddy en service (systemd / conteneur), renouvellement auto géré.

### 5.2 Côté app
- [ ] Saisir l'URL en **`https://nas.exemple.fr`** (sans port — 443 par défaut).
- [ ] iOS : **plus besoin d'exception ATS** (certificat publiquement valide). Retirer/limiter les clés ATS de [app.json](mobile/app.json) côté iOS.
- [ ] Android : le `usesCleartextTraffic` devient **inutile** → on peut le retirer (ou le garder le temps de la transition pour les anciens builds pointant encore sur `http://IP`).

### 5.3 Compatibilité / transition
- [ ] **Garder l'agent capable des deux** un temps : HTTP sur LAN pour les anciens APK Android déjà déployés, HTTPS via Caddy pour le nouveau monde iOS. La variable d'écoute (`127.0.0.1` vs `0.0.0.0`) permet de basculer proprement.
- [ ] **Serveur de démo App Store** (cf. [IOS-MIGRATION.md](IOS-MIGRATION.md) §8 bis) : **doit** être en HTTPS avec certificat **publiquement valide** (pas auto-signé) pour que le reviewer Apple puisse s'y connecter sans installer de profil.

---

## 6. Variante — Option A avec Tailscale (sans domaine à soi)

Si on reste sur Tailscale, le plus rapide :
- [ ] Activer **MagicDNS** + **HTTPS** dans l'admin Tailscale.
- [ ] `tailscale cert nas.<tailnet>.ts.net` sur l'hôte → certificat + clé valides.
- [ ] Pointer Caddy (ou directement `https.createServer`) sur ces fichiers.
- [ ] L'app saisit `https://nas.<tailnet>.ts.net`.
- ✅ HTTPS valide, **zéro domaine, zéro port ouvert**. ⚠️ Ne marche **que** sur le tailnet (l'iPhone doit avoir Tailscale actif) — et le **serveur de démo App Store** devra, lui, être joignable hors Tailscale (donc option domaine pour la review).

---

## 7. Décisions à trancher

- [ ] **Option TLS** : Caddy (reco) vs TLS natif dans l'agent ?
- [ ] **Source du certificat** : domaine + DNS-01 (souverain, marche partout) vs `tailscale cert` (zéro domaine mais lié à Tailscale) ?
- [ ] **Cas du serveur de démo App Store** : prévoir un endpoint HTTPS public à certificat valide pour la review (indépendant du tunnel).
- [ ] **Transition Android** : double écoute HTTP+HTTPS pendant combien de temps avant de couper le HTTP ?

---

*Voir aussi : [IOS-MIGRATION.md](IOS-MIGRATION.md) (ATS / review), [CONFIGURATION.md](CONFIGURATION.md) (mise en place agent & accès distant), [WIREGUARD-MIGRATION.md](WIREGUARD-MIGRATION.md) (tunnel souverain).*
