# TODO - SOGOMS V1 Minimale

Objectif : valider l'architecture avec 2-3 microservices basiques.

## Phase 0 : Infrastructure

- [x] **Container gw3** : Alpine sur IN3 (13.23.33.5)
- [x] **Config Prokov** : routes + scénarios YAML (auth, projects, tasks, tags, statuses)
- [x] **Nginx host IN3** : routing /api/ → gw3:8080, / → dva-front

## Phase 1 : Protocole IPC

- [x] `internal/protocol/message.go` : structs Request/Response JSON
- [x] `internal/protocol/server.go` : listener Unix socket
- [x] `internal/protocol/client.go` : client pour appeler les services

## Phase 2 : Microservice DB

- [x] `cmd/sogoms/db/main.go` : point d'entrée
- [x] Connexion MariaDB (pool par application)
- [x] Action `query` : SELECT multi-résultats
- [x] Action `query_one` : SELECT un résultat
- [x] Action `insert` : INSERT retourne insert_id
- [x] Action `update` : UPDATE retourne affected_rows
- [x] Action `delete` : DELETE retourne affected_rows
- [x] Écoute sur `/run/sogoms-db.1.sock`
- [x] Test standalone sogoms-db

## Phase 3 : Config

- [x] `internal/config/config.go` : lecture YAML + registry par host
- [x] `internal/config/routes.go` : parser routes (intégré dans config.go)

## Phase 4 : Gateway HTTP

- [x] `cmd/sogoway/main.go` : serveur HTTP :8080
- [x] Routing par host → charge le bon fichier routes (prokov.yaml)
- [x] `internal/auth/jwt.go` : génération + validation JWT (HS256)
- [x] `internal/auth/password.go` : hash + verify password (bcrypt)
- [x] Endpoint `POST /api/auth/login` : vérifie credentials, retourne JWT
- [x] Endpoint `GET /api/auth/me` : valide JWT, retourne user
- [x] Endpoint `POST /api/auth/register` : crée user, retourne JWT
- [x] Communication avec sogoms-db via Unix socket
- [x] Test standalone sogoway

## Phase 5 : Superviseur

- [x] `cmd/sogoctl/main.go` : point d'entrée
- [x] Config `config/sogoctl.yaml` : services à lancer
- [x] Lancement sogoms-db + sogoway (avec dépendances)
- [x] Health check (socket + HTTP)
- [x] Redémarrage automatique si crash

## Phase 6 : Test de validation

```bash
# 1. Lancer sogoctl (démarre les services)
./sogoctl

# 2. Login
curl -X POST https://prokov.unikoffice.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","password":"secret"}'
# → {"success":true,"data":{"token":"eyJ...","user":{...}}}

# 3. Vérifier le token
curl https://prokov.unikoffice.com/api/auth/me \
  -H "Authorization: Bearer eyJ..."
# → {"success":true,"data":{"user":{...}}}
```

- [x] Test login OK
- [x] Test /me avec token valide OK
- [x] Test /me sans token → 401

## Phase 7 : Microservice Logs

- [x] `cmd/sogoms/logs/main.go` : point d'entrée
- [x] Écoute sur Unix socket `/run/sogoms-logs.1.sock`
- [x] Actions `log_error`, `log_event` : écriture dans fichiers
- [x] Format fichiers : `/var/log/sogoms/{app}-{YYYYMMDD}-{type}.log`
- [x] Rotation automatique : suppression des fichiers > 30 jours
- [x] Paramètre `retention_days` dans config (`config/routes/prokov.yaml`)
- [x] Intégration avec sogoway et sogoms-db

## Phase 8 : Système de Queries YAML

- [x] Structure `config/queries/{app}/*.yaml`
- [x] Requêtes SQL externalisées (pas de recompilation)
- [x] `internal/config/config.go` : QueryConfig, GetQuery(), Build()
- [x] Placeholders `:user_id`, `:id`, etc.
- [x] Filtres par rôle (default, admin)
- [x] Login enrichi : charge projects, tasks, tags, statuses

## Phase 9 : CRUD Générique

- [x] Routing `/api/{resource}` dans sogoway
- [x] GET list/show avec filtres YAML
- [x] POST create avec fields YAML
- [x] PUT update avec fields + filtres YAML
- [x] DELETE avec filtres YAML
- [x] Config YAML pour projects, tasks, tags, statuses
- [x] Sécurité : filtre user_id automatique

## Phase 10 : Améliorations Deploy

- [x] `deploy.sh` : build sogoms-logs
- [x] `deploy.sh` : backup archives dans `/home/pierre/samba/back/sogoms/`
- [x] `deploy.sh` : redémarrage auto sogoctl
- [x] `deploy.sh` : kill propre des processus zombies
- [x] Documentation `DOCTECH.md`
- [x] Version 1.0.1

## Phase 11 : Microservice Crypt

- [ ] `cmd/sogoms/crypt/main.go` : point d'entrée
- [ ] Écoute sur Unix socket `/run/sogoms-crypt.1.sock`
- [ ] Action `encrypt` : chiffre une donnée (AES-256-GCM)
- [ ] Action `decrypt` : déchiffre une donnée
- [ ] Action `hash` : hash irréversible (SHA-256)
- [ ] Clé de chiffrement par application (`/secrets/{app}_crypt_key`)
- [ ] Intégration avec sogoway pour champs sensibles
- [ ] Config YAML : liste des champs à chiffrer par table
- [ ] Application Prokov : chiffrement `users.email`

## Phase 12 : Microservices Email

### 12a. sogoms-smtp (Envoi)

- [x] `cmd/sogoms/smtp/main.go` : point d'entrée
- [x] Écoute sur Unix socket `/run/sogoms-smtp.1.sock`
- [x] Action `send` : envoi email simple (to, subject, body, html)
- [x] Action `send_template` : envoi avec template YAML
- [x] Action `send_bulk` : envoi en masse (liste de destinataires)
- [x] Config SMTP par application (`config/routes/{app}.yaml`)
- [x] Support TLS/STARTTLS
- [x] Templates YAML (`config/emails/{app}/*.yaml`)
- [ ] Queue d'envoi avec retry en cas d'échec

### 12b. sogoms-imap (Lecture)

- [ ] `cmd/sogoms/imap/main.go` : point d'entrée
- [ ] Écoute sur Unix socket `/run/sogoms-imap.1.sock`
- [ ] Action `list` : liste les emails (folder, limit, offset)
- [ ] Action `fetch` : récupère un email complet (uid)
- [ ] Action `delete` : supprime un email
- [ ] Action `mark_read` : marque comme lu
- [ ] Action `move` : déplace vers un autre dossier
- [ ] Config IMAP par application (`config/routes/{app}.yaml`)
- [ ] Support IMAP IDLE pour notifications temps réel

### 12c. sogoms-mailproc (Traitement)

- [ ] `cmd/sogoms/mailproc/main.go` : point d'entrée
- [ ] Écoute sur Unix socket `/run/sogoms-mailproc.1.sock`
- [ ] Action `parse` : parse un email (headers, body, attachments)
- [ ] Action `apply_rules` : applique des règles configurées
- [ ] Config YAML : règles par application (`config/mailrules/{app}.yaml`)
- [ ] Webhooks : notification vers URL externe
- [ ] Intégration Prokov : email entrant → création de tâche

## Phase 13 : Microservice Cron

- [x] `cmd/sogoms/cron/main.go` : point d'entrée
- [x] `internal/cron/scheduler.go` : parser cron + calcul next run
- [x] Écoute sur Unix socket `/run/sogoms-cron.1.sock`
- [x] Config YAML par application (`config/apps/{app}/cron.yaml`)
- [x] Parser cron schedule (format standard `* * * * *`)
- [x] Support timezone (Europe/Paris)
- [x] Retry configurable (max_attempts, delay)
- [x] Historique des exécutions (configurable, défaut 7 jours)
- [x] Action `list` : liste les jobs configurés avec prochain run
- [x] Action `trigger` : déclenche un job manuellement
- [x] Action `status` : historique des dernières exécutions
- [x] Type `service` : appel service interne (sogoms-smtp, sogoms-db, etc.)
- [x] Type `http` : appel HTTP (GET/POST) vers endpoint interne ou externe
- [x] Type `query_email` : requête DB + envoi email groupé par user
- [x] Logging des exécutions dans sogoms-logs
- [x] Application Prokov : email quotidien `tasks_today` (8h00 lun-ven)
- [x] Intégration sogoctl.yaml
- [x] Intégration deploy.sh

## Phase 14 : Push Temps Réel (MQTT)

### 14a. Infrastructure Mosquitto

- [ ] Installation Mosquitto sur gw3 (Alpine: `apk add mosquitto`)
- [ ] Config `/etc/mosquitto/mosquitto.conf`
- [ ] Auth par user/password ou plugin JWT
- [ ] Port 1883 (MQTT) + 9001 (WebSocket)
- [ ] TLS optionnel pour production

### 14b. sogoms-push

- [ ] `cmd/sogoms/push/main.go` : point d'entrée
- [ ] Écoute sur Unix socket `/run/sogoms-push.1.sock`
- [ ] Connexion au broker MQTT
- [ ] Config YAML par application (`config/push/{app}.yaml`)
- [ ] Action `publish` : publie un message sur un topic
- [ ] Action `notify_user` : publie vers `{app}/user/{user_id}/{channel}`
- [ ] Action `broadcast` : publie vers tous les users d'une app
- [ ] Topics : notifications, tasks, projects, comments
- [ ] Intégration sogoway : publish auto sur événements CRUD

### 14c. Intégration Flutter

- [ ] Package `mqtt_client` dans Prokov Flutter
- [ ] Service MqttService : connexion, reconnexion auto
- [ ] Subscription aux topics user
- [ ] Mise à jour state en temps réel
- [ ] Notifications in-app

## Phase 15 : Schema-Driven API (Socle SOGOMS)

Cette phase transforme SOGOMS en générateur d'API automatique.

### 15a. Définition du Schema

- [x] Format `config/schemas/{app}.yaml` : tables, fields, relations
- [x] Types supportés : int, string, text, float, date, datetime, json
- [x] Contraintes : primary, auto, unique, required, default
- [x] Relations : foreign key avec `foreign: table.field`
- [x] Sécurité : `filter: owner` pour filtrage auto par user_id
- [ ] Auth : `auth: login`, `auth: password` pour détection auto
- [x] CRUD : liste des opérations autorisées par table
- [ ] Filtres custom : définition de filtres nommés
- [ ] Ordre par défaut : `order: "position ASC"`

### 15b. Introspection DB (via API admin)

- [x] Action `introspect` dans sogoms-db : scan INFORMATION_SCHEMA
- [x] Endpoint `GET /api/_admin/schema/introspect` : retourne JSON
- [x] Endpoint `POST /api/_admin/schema/generate` : génère schema.yaml
- [x] Détection auto : types, clés primaires/étrangères, contraintes
- [x] Détection pattern `filter: owner` sur colonnes `user_id`
- [ ] Commande `validate {app}` : valide le schema
- [ ] Commande `diff {app}` : compare schema vs DB réelle
- [ ] Commande `migrate {app}` : génère SQL de migration

### 15c. Runtime Dynamique (sogoway)

- [x] Chargement schema au démarrage
- [x] Routes CRUD auto-générées depuis schema
- [x] Validation des inputs selon types/contraintes
- [x] Filtrage user_id automatique (filter: owner)
- [ ] Gestion relations (include, nested)
- [x] Pas de fichiers queries YAML requis (optionnels pour override)

### 15d. Dictionnaire de Données

- [ ] Endpoint `/api/_schema` : expose le schema (pour admin/debug)
- [ ] Endpoint `/api/_schema/{table}` : détail d'une table
- [ ] Documentation auto-générée
- [ ] Utilisable par Flutter pour génération de formulaires

## Phase 16 : Réorganisation Config par Application

Objectif : regrouper tous les fichiers d'une application dans un seul dossier.

### 16a. Nouvelle structure

```
config/
├── apps/
│   └── {app}/
│       ├── app.yaml           ← config principale (ex routes/{app}.yaml)
│       ├── schema.yaml        ← schema DB généré
│       ├── queries/           ← requêtes SQL
│       │   ├── auth.yaml
│       │   ├── projects.yaml
│       │   └── ...
│       ├── scenarios/         ← orchestrations complexes
│       │   └── auth/
│       │       └── login.yaml
│       └── emails/            ← templates email
│           └── welcome.yaml
└── sogoctl.yaml
```

### 16b. Migration

- [x] Créer `config/apps/prokov/` avec nouvelle structure
- [x] Migrer `config/routes/prokov.yaml` → `config/apps/prokov/app.yaml`
- [x] Migrer `config/schemas/prokov.yaml` → `config/apps/prokov/schema.yaml`
- [x] Migrer `config/queries/prokov/` → `config/apps/prokov/queries/`
- [x] Migrer `config/scenarios/prokov/` → `config/apps/prokov/scenarios/`
- [x] Migrer `config/emails/prokov/` → `config/apps/prokov/emails/`

### 16c. Adaptation du code

- [x] `internal/config/config.go` : nouveau chemin de chargement
- [x] `internal/config/config.go` : charger schema.yaml (optionnel)
- [x] `cmd/sogoway/main.go` : adapter handleSchemaGenerate()
- [x] `deploy.sh` : adapter les chemins de déploiement
- [x] Supprimer anciens dossiers après validation

### 16d. Avantages

- Clarté : tout ce qui concerne une app dans un seul dossier
- Portabilité : copier/sauvegarder une app = copier un dossier
- Scalabilité : ajouter une app = créer un dossier dans `apps/`
- Cohérence : plus de répétition du nom d'app partout

## Phase 17 : Interface Web Administration (sogoms-admin)

### 17a. Backend Go

- [x] `internal/admin/config.go` : chargement admin_users.yaml
- [x] `internal/admin/permissions.go` : vérification des droits
- [x] `internal/admin/audit.go` : logging des actions vers sogoms-logs
- [x] `cmd/sogoms/admin/session.go` : sessions en mémoire, cookies signés HMAC-SHA256
- [x] `cmd/sogoms/admin/middleware.go` : auth, CSRF, rate limiting
- [x] `cmd/sogoms/admin/services.go` : appels vers services (db, logs, cron)
- [x] `cmd/sogoms/admin/handlers.go` : handlers HTTP (login, dashboard, logout)
- [x] `cmd/sogoms/admin/main.go` : serveur HTTP :9000

### 17b. Frontend Templates

- [x] `templates/layout.html` : layout commun avec htmx + Pico.css
- [x] `templates/login.html` : page de connexion avec CSRF
- [x] `templates/dashboard.html` : dashboard principal
- [x] `templates/partials/apps_list.html` : liste apps (htmx)
- [x] `templates/partials/services_status.html` : statut services (htmx)

### 17c. Sécurité

- [x] Passwords : bcrypt cost=12
- [x] Sessions : Cookie HttpOnly + Secure + SameSite=Strict
- [x] CSRF : Token par session, vérifié sur POST
- [x] Rate limiting : 5 tentatives/min par IP sur login
- [x] Audit : Toutes actions loggées vers sogoms-logs

### 17d. Rôles et Permissions

- [x] Super-admin : accès global à toutes les apps et services
- [x] App-admin : accès limité aux apps assignées avec permissions fines
- [x] Permissions granulaires : schema:*, queries:*, emails:*, cron:*, logs:*, db:*

### 17e. Intégration

- [x] `config/sogoctl.yaml` : ajout service sogoms-admin
- [x] `deploy.sh` : build et déploiement sogoms-admin
- [x] Configuration Nginx : admin.sogoms.com → :9000

### 17f. Configuration requise

```yaml
# /secrets/admin_users.yaml
session:
  secret_file: /secrets/admin_session_secret
  max_age: 3600
  cookie_name: sogoms_admin_sid

rate_limit:
  login_max: 5
  login_window: 60

users:
  - username: pierre
    password_hash: "$2a$12$..."
    role: super_admin
    email: pierre@example.com
```

### 17g. Double Authentification (2FA) - OBLIGATOIRE

**Prérequis de sécurité** : l'accès à l'admin SOGOMS doit être protégé par 2FA.

- [x] Package Go `github.com/pquerna/otp` pour TOTP
- [x] Package Go `github.com/skip2/go-qrcode` pour QR codes
- [x] Stockage 2FA dans admin_users.yaml (two_fa_enabled, two_fa_secret, backup_codes)
- [x] Enrôlement TOTP :
  - [x] Page `/admin/2fa/setup` : configuration 2FA
  - [x] Génération secret TOTP (base32, 160 bits)
  - [x] Affichage QR code pour scan (Google Auth, Authy, etc.)
  - [x] Saisie code de vérification pour activer
  - [x] Génération 10 codes de backup format XXXX-XXXX (usage unique)
- [x] Login avec 2FA :
  - [x] Après password valide → page saisie code TOTP (`/admin/2fa/verify`)
  - [x] Validation code TOTP (fenêtre ±30s)
  - [x] Option "code de backup" si téléphone perdu
  - [x] Session marquée `TwoFAVerified`
- [ ] Fallback Email OTP :
  - [ ] Si TOTP non configuré → envoi code 6 chiffres par email
  - [ ] Code valide 10 minutes, usage unique
  - [ ] Utilise sogoms-smtp existant
- [x] Politique :
  - [x] 2FA obligatoire pour rôles configurés (`required_roles`)
  - [x] 2FA optionnel pour autres rôles
  - [x] Forcer configuration 2FA à la première connexion si requis
- [x] Recovery :
  - [x] Reset 2FA par super_admin (page `/admin/users`)
  - [x] Audit log des actions 2FA (2fa_reset loggé)
- [x] Page `/admin/security` : gestion 2FA utilisateur
- [x] Page `/admin/users` : liste utilisateurs + bouton Reset 2FA (super_admin)
- [x] Config admin_users.yaml :
  ```yaml
  two_fa:
    enabled: true
    issuer_name: "SOGOMS Admin"
    required_roles: [super_admin]

  users:
    - username: pierre
      password_hash: "$2a$12$..."
      role: super_admin
      email: pierre@example.com
      two_fa_enabled: true
      two_fa_secret: "BASE32SECRET..."
      backup_codes: ["$2a$...", ...]  # bcrypt hashed
  ```

## Hors scope V1

- sogorch (orchestrateur scénarios)
- sogoms-pdf, sogoms-storage
- Multi-tenant avancé (workspaces, partage)
- Rate limiting
- Rôles utilisateurs (admin, manager, user)

## Phase 19 : Création d'App via Admin UI

Objectif : permettre la création et configuration d'une app directement depuis l'interface admin.

### 19a. Formulaire de création

- [x] Page `/admin/apps/new` : formulaire création app
- [x] Champs : nom app, version, base_path
- [x] Champs hosts : liste des domaines
- [x] Champs database : host, port, user, password, name
- [x] Champs auth : JWT secret (auto-généré ou manuel), expiry
- [ ] Validation : test connexion DB avant création
- [x] Création : génère `config/apps/{app}/app.yaml`

### 19b. Introspection et génération schema

- [x] Bouton "Scanner la base" : appelle introspection DB
- [x] Génération automatique `schema.yaml` depuis INFORMATION_SCHEMA
- [x] Détection : types, clés primaires/étrangères, contraintes
- [x] Détection auto `filter: owner` sur colonnes `user_id`
- [x] Sauvegarde `config/apps/{app}/schema.yaml`

### 19c. Bouton "Update Schema"

- [x] Relecture structure DB (nouvelle introspection)
- [x] Mise à jour schema.yaml (nouvelles tables/colonnes)
- [x] Régénération routes CRUD automatiques
- [x] Rechargement registry après scan
- [x] Rechargement automatique sogoway via SIGHUP (socket sogoctl)

Note : le bouton "Scanner la base" (19b) fait office d'Update Schema.

### 19d. Affichage dans Admin

- [ ] Page détail app : liste tables avec colonnes
- [ ] Page détail app : liste routes générées
- [ ] Page détail app : dictionnaire des données (types, contraintes)
- [ ] Indicateur : schema synchronisé / désynchronisé avec DB
- [ ] Modale détail table : colonnes (nom, type, nullable, default, contraintes)
- [ ] Modale détail route : query SQL, filtres, champs autorisés

### 19f. Génération auto login_data

- [x] Après scan schema, regénérer `login_data` dans `queries/auth.yaml`
- [x] Pour chaque table avec `filter: owner` : SELECT toutes colonnes WHERE user_id = ?
- [x] Préserver le reste du fichier auth.yaml (user_by_email, etc.)

### 19e. Gestion des secrets

- [ ] Génération auto fichiers secrets (`/secrets/{app}_*`)
- [ ] DB password : saisi une fois, stocké dans fichier
- [ ] JWT secret : auto-généré (openssl rand -base64 32)
- [ ] Permissions fichiers : 600

## Phase 20 : Soft Delete

Objectif : supporter la suppression logique pour les tables ayant un champ `deleted_at`.

### 20a. Détection lors du scan DB

- [x] Introspection : détecter colonne `deleted_at` (TIMESTAMP ou DATETIME)
- [x] Schema.yaml : ajouter propriété `soft_delete: true` sur la table
- [x] Affichage admin : indicateur visuel tables avec soft delete (*)

### 20b. Comportement DELETE

- [x] Route DELETE : UPDATE `deleted_at = NOW()` au lieu de DELETE physique
- [x] Queries YAML : support soft_delete via schema
- [x] Réponse API : retourner `affected_rows` comme avant
- [x] Support paramètre `raw` dans sogoms-db pour expressions SQL brutes

### 20c. Filtrage automatique SELECT

- [x] Routes list/show : ajouter `WHERE deleted_at IS NULL` automatiquement
- [x] Schema-driven : BuildListQuery/BuildShowQuery avec filtre soft delete
- [x] Queries YAML : fonction addSoftDeleteFilter() pour injection automatique
- [ ] Option `include_deleted: true` pour voir les supprimés (admin)

### 20d. Restauration (optionnel)

- [ ] Route `POST /api/{resource}/{id}/restore` : remet `deleted_at = NULL`
- [ ] Permission spécifique pour restauration
- [ ] Logging de l'action restore

### 20e. Purge définitive (optionnel)

- [ ] Route `DELETE /api/{resource}/{id}/purge` : suppression physique
- [ ] Permission admin requise
- [ ] Confirmation double (paramètre `force=true`)

### 20f. Cascade Soft Delete

- [x] Détecter les tables enfants via FK (ex: tasks.project_id → projects)
- [x] Lors du soft delete parent, soft delete automatique des enfants
- [x] Récursion : petits-enfants supprimés avant enfants (depth-first)
- [x] Option `cascade: true` dans schema.yaml (auto-détecté lors du scan)
- [x] Auto-détection : cascade activé si parent a soft_delete ET enfants avec soft_delete
- [ ] Logging des suppressions en cascade

---

## Phase 21 : Infrastructure Management

Objectif : piloter depuis l'admin SOGOMS les configurations Nginx, serveurs et containers Incus.

### 21a. Modèle de données

- [x] Table `servers` : id, name, host (IP/hostname), vpn_ip, ssh_port, ssh_user, ssh_key_file, has_incus, has_nginx, status
- [x] Table `containers` : id, server_id, name, incus_name, ip, vpn_ip, image, status (running/stopped/unknown)
- [x] Table `nginx_configs` : id, server_id, domain, type, template, upstream, ssl_enabled, config_content, status
- [x] Table `app_bindings` : id, app_id, container_id, nginx_config_id, server_id, type
- [x] Stockage : SQLite local `/data/infra.db` (flag `-infra-db`)
- [x] Migration : auto-création tables au démarrage (`internal/infra/migrations.go`)

### 21b. SSH Pool (intégré dans sogoms-admin)

- [x] `internal/infra/ssh.go` : client SSH avec pool de connexions
- [x] Pool de connexions SSH vers serveurs configurés
- [x] Reconnexion automatique en cas de perte (isAlive check)
- [x] Méthodes SSH :
  - [x] `Exec` / `ExecSimple` : exécute commande sur serveur
  - [x] `WriteFile` / `ReadFile` : lecture/écriture fichiers distants
  - [x] `CopyFile` / `CopyFrom` : copie fichiers local ↔ distant
  - [x] `StreamExec` : exécution avec streaming stdout/stderr
- [x] Config : clé SSH stockée dans SQLite (chemin fichier)
- [x] Sécurité : accès restreint super_admin uniquement

### 21c. Gestion Incus (containers)

- [x] `internal/infra/incus.go` : méthodes Incus via SSH
- [x] Action `ListIncusContainers` : liste containers (`incus list --format json`)
- [ ] Action `incus_create` : crée un container (image, nom, config)
- [x] Action `StartIncusContainer` : démarre un container
- [x] Action `StopIncusContainer` : arrête un container (graceful)
- [x] Action `RestartIncusContainer` : redémarre un container
- [ ] Action `incus_delete` : supprime un container (avec confirmation)
- [x] Action `ExecInContainer` : exécute une commande dans un container
- [ ] Action `incus_copy` : copie un container (backup/clone)
- [ ] Action `incus_move` : migre un container vers un autre serveur
- [ ] Action `incus_snapshot` : crée un snapshot
- [x] Sync : synchronisation containers Incus → base SQLite
- [ ] Templates : images préconfigurées (alpine-sogoms, alpine-node, alpine-nginx)
- [ ] Réseau : attribution IP automatique ou manuelle

### 21d. Gestion Nginx

- [x] `internal/infra/nginx.go` : méthodes Nginx via SSH
- [ ] Templates Nginx dans `config/nginx-templates/`
  - [ ] `frontend.conf.tmpl` : proxy vers container frontend
  - [ ] `api.conf.tmpl` : proxy vers sogoway (local ou distant via VPN)
  - [ ] `admin.conf.tmpl` : proxy vers sogoms-admin
  - [ ] `ssl.conf.tmpl` : config SSL commune (Let's Encrypt)
- [x] Action `GenerateNginxProxyConfig` : génère config proxy standard
- [x] Action `DeployNginxSite` : écrire + activer + recharger
- [x] Action `TestNginxConfig` : `nginx -t` sur le serveur cible
- [x] Action `ReloadNginx` : `systemctl reload nginx` sur le serveur cible
- [x] Action `ListNginxSites` : liste sites-available/enabled
- [x] Action `EnableNginxSite` / `DisableNginxSite` : gestion liens symboliques
- [x] Action `DeleteNginxSite` : supprime une config
- [x] Sync : synchronisation sites Nginx → base SQLite
- [x] Gestion Let's Encrypt : `RequestSSLCertificate` via certbot
- [ ] Rollback : sauvegarde config avant modification

### 21e. Interface Admin

- [x] Page `/admin/infra` : dashboard infrastructure (liste serveurs, stats)
- [x] Lien "Infra" dans header (super_admin only)
- [x] Section Serveurs :
  - [x] Liste serveurs avec statut (online/offline/unknown)
  - [x] Badges Incus/Nginx pour services disponibles
  - [x] Bouton test connexion SSH
  - [x] Formulaire ajout serveur (nom, host, vpn_ip, ssh_user, ssh_key_file, port)
  - [x] Page détail serveur : containers, configs nginx
  - [x] Bouton suppression serveur
- [x] Section Containers :
  - [x] Liste containers par serveur
  - [x] Statut (running/stopped/unknown)
  - [x] Actions : start, stop, restart
  - [x] Bouton sync depuis Incus
  - [ ] Formulaire création container (serveur, image, nom, IP)
  - [ ] Logs container (dernières lignes)
- [x] Section Nginx :
  - [x] Liste sites par serveur/domaine
  - [x] Statut : active/inactive
  - [x] Bouton sync depuis serveur
  - [x] Bouton reload Nginx
  - [ ] Éditeur config (lecture seule ou édition avancée)
  - [ ] Historique déploiements
- [ ] Section Apps :
  - [ ] Vue unifiée : app → container frontend + config nginx + API sogoms
  - [ ] Wizard création app complète (voir 21f)

**⚠️ À TESTER** : Interface infra déployée, valider fonctionnement avec serveur réel.

### 21f. Orchestration (Workflows)

Workflows automatisés pour opérations complexes.

- [ ] Workflow `app_create_full` : création app complète
  1. Créer container frontend sur serveur cible
  2. Configurer container (packages, user, etc.)
  3. Générer config Nginx frontend
  4. Générer config Nginx API (proxy vers sogoway)
  5. Déployer configs Nginx
  6. Créer config app SOGOMS (`config/apps/{app}/`)
  7. Recharger sogoway
- [ ] Workflow `app_migrate` : migration app vers autre serveur
  1. Snapshot container source
  2. Copier vers serveur destination
  3. Mettre à jour configs Nginx
  4. Basculer DNS (notification)
  5. Supprimer ancien container (optionnel)
- [ ] Workflow `ssl_setup` : configuration SSL
  1. Vérifier DNS pointe vers serveur
  2. Exécuter certbot
  3. Mettre à jour config Nginx
  4. Recharger Nginx
- [ ] Logging : toutes étapes loggées dans sogoms-logs
- [ ] Rollback : annulation automatique si échec

### 21g. API Interne

Endpoints admin pour piloter l'infrastructure.

- [ ] `GET /admin/api/infra/servers` : liste serveurs
- [ ] `POST /admin/api/infra/servers` : ajoute serveur
- [ ] `DELETE /admin/api/infra/servers/{id}` : supprime serveur
- [ ] `POST /admin/api/infra/servers/{id}/test` : teste connexion
- [ ] `GET /admin/api/infra/containers` : liste containers (tous serveurs)
- [ ] `GET /admin/api/infra/containers/{server_id}` : containers d'un serveur
- [ ] `POST /admin/api/infra/containers` : crée container
- [ ] `POST /admin/api/infra/containers/{id}/start` : démarre
- [ ] `POST /admin/api/infra/containers/{id}/stop` : arrête
- [ ] `DELETE /admin/api/infra/containers/{id}` : supprime
- [ ] `GET /admin/api/infra/nginx` : liste configs nginx
- [ ] `POST /admin/api/infra/nginx/generate` : génère config
- [ ] `POST /admin/api/infra/nginx/deploy` : déploie config
- [ ] `POST /admin/api/infra/nginx/reload/{server_id}` : reload nginx
- [ ] `POST /admin/api/infra/workflows/{name}` : lance workflow

### 21h. Configuration exemple

```yaml
# /secrets/infra_servers.yaml
servers:
  - name: IN3
    host: 195.154.80.116
    vpn_ip: 11.1.2.1
    ssh_user: root
    ssh_key_file: /secrets/ssh_in3_key
    ssh_port: 22
    type: host
    incus: true

  - name: IN4
    host: 195.154.xx.xx
    vpn_ip: 11.1.2.14
    ssh_user: root
    ssh_key_file: /secrets/ssh_in4_key
    ssh_port: 22
    type: host
    incus: true

# Templates Nginx
nginx:
  templates_dir: /config/nginx-templates
  certbot_email: admin@sogoms.com
```

```nginx
# config/nginx-templates/api.conf.tmpl
server {
    server_name {{.Domain}};

    location /api/ {
        proxy_pass http://{{.ApiUpstream}};
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    {{if .SSLEnabled}}
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/{{.Domain}}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/{{.Domain}}/privkey.pem;
    {{else}}
    listen 80;
    {{end}}
}
```

### 21i. Sécurité

- [ ] Clés SSH : fichiers séparés dans `/secrets/`, permissions 600
- [ ] Accès : super_admin uniquement pour toutes opérations infra
- [ ] Audit : toutes actions loggées (qui, quoi, quand, serveur)
- [ ] Rate limiting : max 10 opérations/minute par user
- [ ] Confirmation : double confirmation pour actions destructives (delete container)
- [ ] Isolation : sogoms-infra tourne avec user dédié

### 21j. Dépendances

- Phase 17 (Admin UI) ✅
- Phase 19 (Création App) ✅
- Accès SSH aux serveurs (clés à configurer)
- Incus installé sur les serveurs hôtes
- [x] Package Go : `golang.org/x/crypto/ssh`
- [x] Package Go : `github.com/mattn/go-sqlite3`

---

## Phase 18 : Application Geosector (Janvier-Février 2026)

Migration de l'API PHP 8.3 existante vers SOGOMS pour l'application Flutter (Web + mobiles).

### 18a. Préparation

- [ ] Introspection DB MariaDB existante
- [ ] Génération schema.yaml depuis introspection
- [ ] Création `config/apps/geosector/`
- [ ] Analyse des endpoints PHP existants

### 18b. Migration

- [ ] Configuration app.yaml (DB, auth, hosts)
- [ ] Adaptation des queries spécifiques
- [ ] Migration des endpoints custom si nécessaire
- [ ] Configuration jobs cron (si applicable)
- [ ] Configuration emails (si applicable)

### 18c. Tests et bascule

- [ ] Tests avec app Flutter (web)
- [ ] Tests avec app Flutter (iOS/Android)
- [ ] Configuration Nginx geosector.sogoms.com
- [ ] Bascule DNS production
- [ ] Monitoring post-migration
