# SOGOMS - Service Oriented GO MicroServices

> Architecture modulaire, configurable et multi-tenant pour plateformes SaaS

**Website** : https://sogoms.com

---

## 1. Vision et Principes

### 1.1 Concept

SOGOMS est une architecture de plateforme permettant de construire des applications SaaS modulaires, hautement configurables et multi-tenant.

L'idée centrale : **une seule plateforme, plusieurs services, plusieurs clients, configurations illimitées.**

### 1.2 Principes fondamentaux

| Principe | Description |
|----------|-------------|
| **Modularité** | Chaque fonctionnalité = un binaire Go indépendant |
| **Configuration over Code** | Comportements définis en YAML, pas en dur |
| **Multi-tenant natif** | Isolation des données et configs par client |
| **Orchestration** | Workflows complexes via scénarios paramétrables |
| **Scalabilité horizontale** | Chaque binaire peut avoir N instances |
| **Simplicité** | Un container, plusieurs processus supervisés |

### 1.3 Cas d'usage cibles

- Plateformes SaaS B2B multi-clients
- Applications métier avec workflows personnalisables
- Systèmes de gestion documentaire (PDF, signatures, archivage)
- Plateformes de communication (emails, notifications, SMS)
- Back-offices d'applications mobiles Flutter

### 1.4 Composants de l'écosystème

| Composant | Description |
|-----------|-------------|
| **SOGOMS** | Plateforme principale (ce document) |
| **SOGOMS Vigil** | Extension monitoring (voir `sogoms-vigil.md`) |

---

## 2. Architecture Globale

### 2.1 Infrastructure

```
                              Internet
                                 │
                                 ▼
┌────────────────────────────────────────────────────────────────────────────┐
│                        IN3 (Dev/Recette) ou IN4 (Prod)                     │
│                             Debian 13 - Host                               │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                            │
│   Nginx Host (:443 TLS → :80 HTTP)                                         │
│      │                                                                     │
│      ├── api-dev.sogoms.com ──→ gw3:8080 (Dev)                            │
│      ├── api.sogoms.com ──────→ gw4:8080 (Prod)                           │
│      └── (autres sites) ──────→ [containers PHP existants]                │
│                                                                            │
├────────────────────────────────────────────────────────────────────────────┤
│                     Bridge Incus : 13.23.33.0/24                           │
│                                                                            │
│   ┌──────────────────────────────────────────────────────────────────┐    │
│   │                    gw3 - 13.23.33.5 (ou gw4)                     │    │
│   │                    Alpine 3.21                                   │    │
│   │                                                                  │    │
│   │   ┌────────────────────────────────────────────────────────┐    │    │
│   │   │                 Sogoctl (superviseur)                  │    │    │
│   │   │                 PID 1 - Admin :9000                    │    │    │
│   │   └────────────────────────┬───────────────────────────────┘    │    │
│   │                            │ supervise                          │    │
│   │   ┌────────────────────────┴───────────────────────────────┐    │    │
│   │   │                                                        │    │    │
│   │   │  Sogoway (:8080)                                       │    │    │
│   │   │      │                                                 │    │    │
│   │   │      ▼ unix socket                                     │    │    │
│   │   │  Sogorch (N instances)                                 │    │    │
│   │   │      │                                                 │    │    │
│   │   │      ▼ unix sockets                                    │    │    │
│   │   │  ┌──────────┬──────────┬──────────┬──────────┐        │    │    │
│   │   │  │sogoms-db │sogoms-pdf│sogoms-   │sogoms-   │        │    │    │
│   │   │  │   (N)    │   (N)    │ email(N) │ stor.(N) │        │    │    │
│   │   │  └──────────┴──────────┴──────────┴──────────┘        │    │    │
│   │   │                                                        │    │    │
│   │   └────────────────────────────────────────────────────────┘    │    │
│   │                                                                  │    │
│   │   /run/           /config/            /data/storage/            │    │
│   │   └── *.sock      ├── sogoctl.yaml    └── tenants/              │    │
│   │                   ├── routes/             └── {tenant}/          │    │
│   │                   └── scenarios/                                 │    │
│   └──────────────────────────────────────────────────────────────────┘    │
│                                                                            │
│   ┌─────────────────┐    ┌─────────────────┐                              │
│   │     maria3      │    │     redis3      │                              │
│   │   13.23.33.4    │    │   13.23.33.6    │                              │
│   │  MariaDB :3306  │    │   Redis :6379   │                              │
│   └─────────────────┘    └─────────────────┘                              │
│                                                                            │
└────────────────────────────────────────────────────────────────────────────┘
```

### 2.2 Containers Incus

| Container | IP | Rôle | Base |
|-----------|-----|------|------|
| **gw3** (dev) / **gw4** (prod) | 13.23.33.5 | Gateway + Orchestrateur + Microservices | Alpine |
| **maria3** / **maria4** | 13.23.33.4 | MariaDB (existant) | Alpine |
| **redis3** / **redis4** | 13.23.33.6 | Cache, sessions, rate-limit (V2+) | Alpine |

### 2.3 Flux de données

```
1. Client HTTPS → Nginx Host (:443)
2. Nginx → Sogoway (:8080) via proxy HTTP
3. Sogoway → Valide JWT → Identifie tenant → Trouve route
4. Sogoway → Sogorch (unix socket)
5. Sogorch → Charge scénario YAML → Exécute steps
6. Sogorch → Sogoms-* (unix sockets) pour chaque step
7. Sogoms-* → Traite (DB, PDF, email...) → Retourne résultat
8. Sogorch → Agrège résultats → Retourne à Sogoway
9. Sogoway → Nginx → Client
```

### 2.4 Identification des Applications Clientes

Chaque application cliente de SOGOMS (Prokov, etc.) est identifiée par son **hostname**.

#### Flow d'identification

```
1. Requête arrive : GET https://prokov.unikoffice.com/api/auth/me
2. Nginx Host → Sogoway (:8080) avec Header "Host: prokov.unikoffice.com"
3. Sogoway parcourt config/routes/*.yaml
4. Sogoway trouve prokov.yaml car "prokov.unikoffice.com" est dans ses "hosts"
5. Sogoway identifie app_id = "prokov"
6. Pour chaque appel à sogoms-db, Sogoway inclut app_id dans la requête
7. Sogoms-db charge config/routes/prokov.yaml → section "database"
8. Sogoms-db exécute la requête SQL sur la DB de l'application
```

#### Configuration obligatoire par application

Chaque fichier `config/routes/{app}.yaml` DOIT contenir :

```yaml
app: prokov                      # Identifiant unique
hosts:                           # Hostnames associés
  - prokov.unikoffice.com
  - prokov.sogoms.com

database:                        # Config DB isolée
  host: 13.23.33.4
  port: 3306
  user: prokov                   # User DB dédié
  password_file: /secrets/prokov_db_pass
  name: prokov                   # Base de données dédiée
```

#### Principe d'isolation

| Élément | Isolation |
|---------|-----------|
| Base de données | Une DB par application |
| User MariaDB | Un user par application |
| Credentials | Fichier séparé par application |
| Données | Aucun partage entre applications |

---

## 3. Binaires Go

### 3.1 Vue d'ensemble

| Binaire | Rôle | Instances | Port/Socket |
|---------|------|-----------|-------------|
| **sogoctl** | Superviseur, admin, monitoring | 1 | TCP :9000 |
| **sogoway** | HTTP Gateway, auth, routing | 1 | TCP :8080 |
| **sogorch** | Orchestrateur, exécute scénarios | N | Unix socket |
| **sogoms-db** | Service accès MariaDB | N | Unix socket |
| **sogoms-pdf** | Service génération PDF | N | Unix socket |
| **sogoms-email** | Service envoi emails | N | Unix socket |
| **sogoms-storage** | Service gestion fichiers | N | Unix socket |

### 3.2 Sogoctl (Superviseur)

Sogoctl est le processus principal (PID 1) qui supervise tous les autres binaires.

#### Responsabilités

- Démarrer/arrêter les binaires au boot
- Health checks périodiques
- Redémarrage automatique en cas de crash
- Load balancing round-robin entre instances
- API d'administration (stats, scaling, logs)
- Registry des instances actives

#### Configuration

```yaml
# /config/sogoctl.yaml

supervisor:
  socket: /run/sogoctl.sock
  admin_port: 9000
  health_interval: 5s
  restart_delay: 1s
  max_restarts: 5

logging:
  level: info
  output: /var/log/sogoms/sogoctl.log

services:
  sogoway:
    binary: /opt/sogoms/bin/sogoway
    instances: 1
    port: 8080
    health_endpoint: /health

  sogorch:
    binary: /opt/sogoms/bin/sogorch
    instances: 2
    socket_pattern: /run/sogorch.{id}.sock
    health_endpoint: /health

  sogoms-db:
    binary: /opt/sogoms/bin/sogoms-db
    instances: 2
    socket_pattern: /run/sogoms-db.{id}.sock
    env:
      MARIA_HOST: 13.23.33.4
      MARIA_PORT: "3306"
      MARIA_USER: sogoms
      MARIA_PASS_FILE: /secrets/maria_password

  sogoms-pdf:
    binary: /opt/sogoms/bin/sogoms-pdf
    instances: 1
    socket_pattern: /run/sogoms-pdf.{id}.sock
    autoscale:
      enabled: true
      min: 1
      max: 5
      metric: queue_depth
      threshold: 10

  sogoms-email:
    binary: /opt/sogoms/bin/sogoms-email
    instances: 1
    socket_pattern: /run/sogoms-email.{id}.sock
    env:
      SMTP_HOST: smtp.example.com
      SMTP_PORT: "587"

  sogoms-storage:
    binary: /opt/sogoms/bin/sogoms-storage
    instances: 1
    socket_pattern: /run/sogoms-storage.{id}.sock
    env:
      STORAGE_BASE: /data/storage
```

#### CLI Sogoctl

```bash
# Statut global
$ sogoctl status

SERVICE        INSTANCE    PID     STATUS    CPU    MEM     UPTIME
sogoway        1           1234    running   2%     45MB    2h15m
sogorch        1           1235    running   5%     32MB    2h15m
sogorch        2           1236    running   3%     30MB    2h15m
sogoms-db      1           1237    running   1%     28MB    2h15m
sogoms-db      2           1238    running   1%     27MB    2h15m
sogoms-pdf     1           1239    running   0%     52MB    2h15m
sogoms-email   1           1240    running   0%     25MB    2h15m

# Scaler un service
$ sogoctl scale sogoms-pdf 3
Scaling sogoms-pdf: 1 → 3
Starting sogoms-pdf.2 ... OK (PID 1241)
Starting sogoms-pdf.3 ... OK (PID 1242)

# Instances d'un service
$ sogoctl instances sogoms-pdf

INSTANCE    PID     SOCKET                        STATUS    REQUESTS
1           1239    /run/sogoms-pdf.1.sock        running   1,234
2           1241    /run/sogoms-pdf.2.sock        running   156
3           1242    /run/sogoms-pdf.3.sock        running   89

# Redémarrer un service
$ sogoctl restart sogorch

# Logs
$ sogoctl logs sogoms-pdf.1 --follow
$ sogoctl logs sogorch --all --since 1h

# Stats temps réel
$ sogoctl top

# Info d'un service
$ sogoctl info sogorch
```

### 3.3 Sogoway (Gateway HTTP)

Point d'entrée HTTP unique pour toutes les requêtes API.

#### Responsabilités

- Réception des requêtes HTTP
- Authentification (JWT, API Keys)
- Identification du tenant
- Routing vers les scénarios
- Rate limiting
- Logging des requêtes

#### Configuration

```yaml
# /config/sogoway.yaml

server:
  port: 8080
  read_timeout: 30s
  write_timeout: 30s
  max_body_size: 10MB

auth:
  jwt:
    secret_env: JWT_SECRET
    algorithm: HS256
    expiration: 24h
    claims:
      tenant_id: tenant
      user_id: sub
      roles: roles
  api_keys:
    enabled: true
    header: X-API-Key
    storage: redis

tenant:
  resolution:
    - type: jwt_claim
      claim: tenant_id
    - type: header
      name: X-Tenant-ID
    - type: subdomain
      pattern: "{tenant}.api.sogoms.com"

rate_limit:
  enabled: true
  storage: redis
  default:
    requests: 1000
    window: 1m
  by_tenant: true

orchestrator:
  pool_size: 10
  timeout: 30s

routes_path: /config/routes

logging:
  level: info
  format: json
  output: stdout

metrics:
  enabled: true
  path: /metrics
```

#### Routes par application

```yaml
# /config/routes/prokov.yaml

app: prokov
version: "1.0"
base_path: /api/prokov

auth:
  required: true
  roles: [user, admin]

routes:
  # Liste des tâches
  - path: /tasks
    method: GET
    scenario: list_tasks
    cache:
      enabled: true
      ttl: 30s

  # Créer une tâche
  - path: /tasks
    method: POST
    scenario: create_task
    rate_limit:
      requests: 100
      window: 1m

  # Détail d'une tâche
  - path: /tasks/{id}
    method: GET
    scenario: get_task

  # Modifier une tâche
  - path: /tasks/{id}
    method: PUT
    scenario: update_task

  # Supprimer une tâche
  - path: /tasks/{id}
    method: DELETE
    scenario: delete_task
    auth:
      roles: [admin]
```

### 3.4 Sogorch (Orchestrateur)

Exécute les scénarios YAML en appelant les microservices.

#### Responsabilités

- Charger et parser les scénarios YAML
- Exécuter les steps séquentiellement ou en parallèle
- Gérer le contexte et les variables
- Appeler les Sogoms via Unix sockets
- Gérer les erreurs, retry, conditions
- Retourner le résultat agrégé

#### Scénario type

```yaml
# /config/scenarios/create_task.yaml

name: create_task
version: "1.0"
description: Créer une tâche et notifier l'assigné

input:
  required:
    - title
    - assigned_to
  optional:
    - description
    - priority
    - notify
  defaults:
    priority: medium
    notify: false

context:
  created_at: "{{now}}"
  created_by: "{{auth.user_id}}"

steps:
  # Valider que l'utilisateur assigné existe
  - id: validate_user
    service: db
    action: query_one
    params:
      query: "SELECT id, email FROM users WHERE id = ? AND tenant_id = ?"
      args: ["{{input.assigned_to}}", "{{tenant.id}}"]
    on_error: abort
    error_message: "Utilisateur assigné non trouvé"

  # Insérer la tâche
  - id: insert_task
    service: db
    action: insert
    params:
      table: tasks
      data:
        tenant_id: "{{tenant.id}}"
        title: "{{input.title}}"
        description: "{{input.description}}"
        priority: "{{input.priority}}"
        assigned_to: "{{input.assigned_to}}"
        status: "pending"
        created_by: "{{context.created_by}}"
        created_at: "{{context.created_at}}"
    on_error: abort

  # Notifier par email (optionnel, async)
  - id: send_notification
    service: email
    action: send
    condition: "{{input.notify == true}}"
    async: true
    params:
      to: "{{steps.validate_user.result.email}}"
      template: task_assigned
      data:
        task_id: "{{steps.insert_task.insert_id}}"
        task_title: "{{input.title}}"
        assigned_by: "{{auth.user_name}}"

output:
  status: 201
  body:
    success: true
    task:
      id: "{{steps.insert_task.insert_id}}"
      title: "{{input.title}}"
      status: "pending"
      created_at: "{{context.created_at}}"
```

#### Syntaxe des scénarios

```yaml
# Conditions
- id: premium_only
  service: billing
  action: check_feature
  condition: "{{tenant.plan == 'premium'}}"

# Boucles
- id: notify_all
  service: email
  action: send
  foreach: "{{input.recipients}}"
  foreach_as: recipient
  params:
    to: "{{recipient.email}}"
    template: notification

# Parallélisme
- id: parallel_tasks
  parallel:
    - id: gen_pdf
      service: pdf
      action: generate
      params: {...}
    - id: send_copy
      service: email
      action: send
      params: {...}

# Retry
- id: external_call
  service: http
  action: post
  retry:
    attempts: 3
    delay: 2s
    backoff: exponential

# Switch/case
- id: route_by_type
  switch: "{{input.document_type}}"
  cases:
    invoice:
      service: pdf
      action: generate_invoice
    contract:
      service: pdf
      action: generate_contract
  default:
    service: pdf
    action: generate_generic
```

### 3.5 Microservices (Sogoms-*)

Chaque microservice est un binaire Go spécialisé.

#### Structure commune

```go
// Chaque Sogoms implémente cette interface
type Service interface {
    Name() string
    Actions() map[string]ActionHandler
    Health() error
}

type ActionHandler func(ctx context.Context, params map[string]any) (any, error)
```

#### Sogoms-db

```yaml
# Actions disponibles
actions:
  - query        # SELECT avec plusieurs résultats
  - query_one    # SELECT avec un seul résultat
  - insert       # INSERT, retourne insert_id
  - update       # UPDATE, retourne affected_rows
  - delete       # DELETE, retourne affected_rows
  - exec         # Requête brute
  - transaction  # Groupe de requêtes transactionnelles
```

#### Sogoms-pdf

```yaml
actions:
  - generate     # Générer un PDF depuis un template
  - merge        # Fusionner plusieurs PDFs
  - split        # Séparer un PDF
  - extract_text # Extraire le texte
  - add_signature # Ajouter une signature
```

#### Sogoms-email

```yaml
actions:
  - send         # Envoyer un email
  - send_bulk    # Envoyer en masse
  - validate     # Valider une adresse email
```

#### Sogoms-storage

```yaml
actions:
  - put          # Stocker un fichier
  - get          # Récupérer un fichier
  - delete       # Supprimer un fichier
  - list         # Lister les fichiers
  - get_url      # Obtenir une URL signée temporaire
```

---

## 4. Communication Inter-Processus

### 4.1 Protocole Unix Socket

Les binaires communiquent via Unix sockets avec un protocole simple basé sur JSON.

#### Format des messages

```
┌─────────────────────────────────────────────────────┐
│  4 bytes   │  N bytes                              │
│  Length    │  JSON Payload                         │
└─────────────────────────────────────────────────────┘
```

#### Requête

```json
{
  "id": "req_abc123",
  "action": "insert",
  "tenant_id": "acme",
  "params": {
    "table": "tasks",
    "data": {
      "title": "Ma tâche",
      "status": "pending"
    }
  },
  "timeout_ms": 5000
}
```

#### Réponse

```json
{
  "id": "req_abc123",
  "status": "success",
  "result": {
    "insert_id": 42,
    "affected_rows": 1
  }
}
```

```json
{
  "id": "req_abc123",
  "status": "error",
  "error": {
    "code": "DB_ERROR",
    "message": "Duplicate entry for key 'title'"
  }
}
```

### 4.2 Load Balancing

Sogoctl maintient un pool de connexions pour chaque service :

```go
type ServicePool struct {
    name      string
    instances []*Instance
    mu        sync.RWMutex
    counter   uint64
}

func (p *ServicePool) Next() *Instance {
    p.mu.RLock()
    defer p.mu.RUnlock()

    // Round-robin
    idx := atomic.AddUint64(&p.counter, 1) % uint64(len(p.instances))
    return p.instances[idx]
}
```

---

## 5. Multi-Tenancy

### 5.1 Identification du tenant

Le tenant est identifié dans cet ordre de priorité :

1. Claim JWT `tenant_id`
2. Header `X-Tenant-ID`
3. Sous-domaine (`acme.api.sogoms.com`)
4. API Key (lookup en base)

### 5.2 Configuration par tenant

```yaml
# /config/tenants/acme.yaml

tenant:
  id: acme
  name: ACME Corporation
  domain: acme.example.com
  plan: premium
  status: active

database:
  prefix: acme_           # Tables préfixées ou schema séparé

limits:
  rate_limit: 5000/min
  storage: 50GB
  users: 100
  api_keys: 20

features:
  - pdf
  - email
  - storage
  - custom_workflows

storage:
  type: local             # local | s3 | minio
  config:
    base_path: /data/storage/tenants/acme

customization:
  branding:
    logo_url: https://acme.example.com/logo.png
    primary_color: "#1a73e8"
  email:
    from_name: ACME Platform
    from_email: noreply@acme.example.com
```

### 5.3 Isolation des données

```sql
-- Chaque table inclut tenant_id
CREATE TABLE tasks (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    tenant_id VARCHAR(50) NOT NULL,
    title VARCHAR(255) NOT NULL,
    description TEXT,
    status ENUM('pending', 'in_progress', 'completed') DEFAULT 'pending',
    assigned_to BIGINT,
    created_by BIGINT NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME ON UPDATE CURRENT_TIMESTAMP,

    INDEX idx_tenant (tenant_id),
    INDEX idx_tenant_status (tenant_id, status)
);

-- Sogoms-db ajoute automatiquement la clause tenant_id
```

---

## 6. Stockage Fichiers

### 6.1 Structure

```
/data/storage/
├── _system/                    # Fichiers système SOGOMS
│   ├── templates/              # Templates PDF, email
│   │   ├── pdf/
│   │   │   ├── invoice.html
│   │   │   └── contract.html
│   │   └── email/
│   │       ├── welcome.html
│   │       └── task_assigned.html
│   └── tmp/                    # Fichiers temporaires
│
└── tenants/
    ├── acme/
    │   ├── documents/          # PDFs générés
    │   ├── uploads/            # Fichiers uploadés
    │   └── tmp/                # Temporaires du tenant
    │
    └── startup/
        ├── documents/
        ├── uploads/
        └── tmp/
```

### 6.2 Interface Storage (évolutive)

```go
type Storage interface {
    Put(ctx context.Context, path string, data []byte) error
    Get(ctx context.Context, path string) ([]byte, error)
    Delete(ctx context.Context, path string) error
    List(ctx context.Context, prefix string) ([]string, error)
    GetURL(ctx context.Context, path string, expiry time.Duration) (string, error)
}

// Implémentations disponibles
// - LocalStorage  : fichiers locaux
// - S3Storage     : AWS S3 / Scaleway Object Storage
// - MinioStorage  : MinIO self-hosted
```

---

## 7. Sécurité

### 7.1 Authentification JWT

```yaml
# Structure du token JWT
header:
  alg: HS256
  typ: JWT

payload:
  sub: "user_123"           # User ID
  tenant: "acme"            # Tenant ID
  roles: ["user", "admin"]  # Rôles
  exp: 1704067200           # Expiration
  iat: 1703980800           # Issued at
```

### 7.2 Rate Limiting

```yaml
# Par défaut
rate_limit:
  default: 1000/min

# Par tenant (override)
rate_limit:
  acme: 5000/min
  startup: 500/min

# Par endpoint (override)
routes:
  - path: /api/heavy-operation
    rate_limit:
      requests: 10
      window: 1m
```

### 7.3 Validation des entrées

Chaque scénario valide ses inputs :

```yaml
input:
  required:
    - email
    - password
  optional:
    - name
  validation:
    email:
      type: string
      format: email
    password:
      type: string
      min_length: 8
```

---

## 8. Structure du Projet

```
sogoms/
├── cmd/
│   ├── sogoctl/                # Superviseur
│   │   └── main.go
│   ├── sogoway/                # Gateway HTTP
│   │   └── main.go
│   ├── sogorch/                # Orchestrateur
│   │   └── main.go
│   └── sogoms/
│       ├── db/                 # Microservice DB
│       │   └── main.go
│       ├── pdf/                # Microservice PDF
│       │   └── main.go
│       ├── email/              # Microservice Email
│       │   └── main.go
│       └── storage/            # Microservice Storage
│           └── main.go
│
├── internal/
│   ├── protocol/               # Protocole Unix socket
│   │   ├── message.go
│   │   ├── client.go
│   │   └── server.go
│   ├── pool/                   # Load balancer interne
│   │   └── pool.go
│   ├── config/                 # Lecture configs YAML
│   │   ├── config.go
│   │   ├── tenant.go
│   │   └── routes.go
│   ├── scenario/               # Exécution scénarios
│   │   ├── parser.go
│   │   ├── executor.go
│   │   └── context.go
│   ├── auth/                   # JWT, API Keys
│   │   ├── jwt.go
│   │   └── apikey.go
│   └── registry/               # Registry des instances
│       └── registry.go
│
├── pkg/
│   └── logger/                 # Logger partagé
│       └── logger.go
│
├── config/
│   ├── sogoctl.yaml            # Config superviseur
│   ├── sogoway.yaml            # Config gateway
│   ├── tenants/                # Configs tenants
│   │   ├── acme.yaml
│   │   └── startup.yaml
│   ├── routes/                 # Routes par application
│   │   └── prokov.yaml
│   └── scenarios/              # Scénarios
│       ├── create_task.yaml
│       ├── update_task.yaml
│       └── delete_task.yaml
│
├── scripts/
│   ├── build.sh                # Build tous les binaires
│   ├── install.sh              # Installation dans container
│   └── dev.sh                  # Lancement dev local
│
├── deploy/
│   └── incus/
│       ├── setup-gw3.sh        # Setup container gw3
│       └── setup-redis3.sh     # Setup container redis3
│
├── go.mod
├── go.sum
├── Makefile
└── README.md
```

---

## 9. Déploiement

### 9.1 Build

```makefile
# Makefile

BINARIES = sogoctl sogoway sogorch sogoms-db sogoms-pdf sogoms-email sogoms-storage
VERSION = $(shell git describe --tags --always)
LDFLAGS = -s -w -X main.version=$(VERSION)

.PHONY: all clean $(BINARIES)

all: $(BINARIES)

sogoctl:
	CGO_ENABLED=0 GOOS=linux go build -ldflags="$(LDFLAGS)" -o dist/sogoctl ./cmd/sogoctl

sogoway:
	CGO_ENABLED=0 GOOS=linux go build -ldflags="$(LDFLAGS)" -o dist/sogoway ./cmd/sogoway

sogorch:
	CGO_ENABLED=0 GOOS=linux go build -ldflags="$(LDFLAGS)" -o dist/sogorch ./cmd/sogorch

sogoms-%:
	CGO_ENABLED=0 GOOS=linux go build -ldflags="$(LDFLAGS)" -o dist/sogoms-$* ./cmd/sogoms/$*

clean:
	rm -rf dist/*

install: all
	scp dist/* gw3:/opt/sogoms/bin/
	ssh gw3 'sogoctl restart all'
```

### 9.2 Setup Container Incus

```bash
#!/bin/bash
# deploy/incus/setup-gw3.sh

# Créer le container
incus launch images:alpine/3.21 gw3

# Configurer l'IP fixe
incus config device override gw3 eth0 ipv4.address=13.23.33.5

# Créer les dossiers
incus exec gw3 -- mkdir -p /opt/sogoms/bin
incus exec gw3 -- mkdir -p /config
incus exec gw3 -- mkdir -p /data/storage/tenants
incus exec gw3 -- mkdir -p /run
incus exec gw3 -- mkdir -p /var/log/sogoms

# Installer les dépendances (pour sogoms-pdf notamment)
incus exec gw3 -- apk add --no-cache \
    chromium \
    font-noto \
    font-noto-emoji

# Copier les binaires
incus file push dist/* gw3/opt/sogoms/bin/

# Copier les configs
incus file push -r config/* gw3/config/

# Configurer sogoctl comme service init
incus exec gw3 -- sh -c 'cat > /etc/init.d/sogoms << EOF
#!/sbin/openrc-run
command=/opt/sogoms/bin/sogoctl
command_args="--config /config/sogoctl.yaml"
pidfile=/run/sogoctl.pid
EOF'

incus exec gw3 -- chmod +x /etc/init.d/sogoms
incus exec gw3 -- rc-update add sogoms default

# Démarrer
incus exec gw3 -- rc-service sogoms start
```

### 9.3 Config Nginx Host

```nginx
# /etc/nginx/sites-available/sogoms

upstream sogoms_gateway {
    server 13.23.33.5:8080;
    keepalive 16;
}

server {
    listen 443 ssl http2;
    server_name api.sogoms.com api-dev.sogoms.com;

    ssl_certificate /etc/letsencrypt/live/sogoms.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sogoms.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;

    access_log /var/log/nginx/sogoms.access.log;
    error_log /var/log/nginx/sogoms.error.log;

    location / {
        proxy_pass http://sogoms_gateway;
        proxy_http_version 1.1;
        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;
        proxy_set_header Connection "";

        proxy_connect_timeout 10s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    location /ws/ {
        proxy_pass http://sogoms_gateway;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400;
    }
}
```

---

## 10. Monitoring

### 10.1 Métriques (via Sogoctl)

```bash
# API Admin :9000

GET /metrics              # Prometheus format
GET /health               # Health check global
GET /status               # Status détaillé JSON
GET /services             # Liste des services et instances
GET /services/{name}      # Détail d'un service
```

### 10.2 Logs

```bash
# Logs centralisés par Sogoctl
/var/log/sogoms/
├── sogoctl.log
├── sogoway.log
├── sogorch.log
├── sogoms-db.log
├── sogoms-pdf.log
├── sogoms-email.log
└── sogoms-storage.log
```

### 10.3 SOGOMS Vigil

Pour un monitoring avancé multi-hosts avec agents, voir **[sogoms-vigil.md](sogoms-vigil.md)**.

---

## 11. Roadmap

### Phase 1 : Foundation (MVP)

- [ ] Sogoctl : superviseur basique (start/stop/restart)
- [ ] Sogoway : routing, auth JWT
- [ ] Sogorch : exécution scénarios simples
- [ ] Sogoms-db : CRUD MariaDB
- [ ] Protocole Unix socket
- [ ] Config YAML (routes + scénarios)

### Phase 2 : Features

- [ ] Multi-tenant complet
- [ ] Sogoms-pdf : génération PDF
- [ ] Sogoms-email : envoi emails
- [ ] Sogoms-storage : gestion fichiers
- [ ] Rate limiting Redis
- [ ] Sogoctl : scaling dynamique

### Phase 3 : Production

- [ ] Health checks avancés
- [ ] Métriques Prometheus
- [ ] Autoscaling basé sur métriques
- [ ] Hot reload des configs
- [ ] Dashboard admin

### Phase 4 : Enterprise

- [ ] Workflows complexes (conditions, boucles, parallélisme)
- [ ] API Keys management
- [ ] Webhooks
- [ ] Multi-région
- [ ] Audit logs

---

## 12. Références

- [Go Chi Router](https://github.com/go-chi/chi) - HTTP routing
- [Go YAML v3](https://github.com/go-yaml/yaml) - Parsing YAML
- [Go MariaDB Driver](https://github.com/go-sql-driver/mysql) - Accès MariaDB
- [Chromedp](https://github.com/chromedp/chromedp) - Génération PDF
- [Incus Documentation](https://linuxcontainers.org/incus/docs/main/) - Containers

---

**Website** : https://sogoms.com
**Documentation** : https://docs.sogoms.com
**API** : https://api.sogoms.com

*Document mis à jour le 2025-01-15 - Version 2.0.0*
