Files
sogoms/DOCTECH.md
Pierre a4694a10d1 SOGOMS v1.0.1 - Microservices logs, smtp et roadmap
Nouveaux services:
- sogoms-logs : logging centralisé avec rotation
- sogoms-smtp : envoi emails avec templates YAML

Nouvelles fonctionnalités:
- Queries YAML externalisées (config/queries/{app}/)
- CRUD générique paramétrable
- Filtres par rôle (default, admin)
- Templates email (config/emails/{app}/)

Documentation:
- DOCTECH.md : documentation technique complète
- README.md : vision et roadmap
- TODO.md : phases 11-15 planifiées

Roadmap:
- Phase 11: sogoms-crypt (chiffrement)
- Phase 12: sogoms-imap/mailproc (emails)
- Phase 13: sogoms-cron (tâches planifiées)
- Phase 14: sogoms-push (MQTT temps réel)
- Phase 15: sogoms-schema (API auto-générée)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 14:58:46 +01:00

13 KiB

SOGOMS - Documentation Technique

Service Oriented GO MicroServices - Plateforme SaaS modulaire multi-tenant.

Version: 1.0.1 Date: 16 décembre 2025


Table des matières

  1. Architecture
  2. Services
  3. Communication IPC
  4. Configuration
  5. API REST
  6. Système de Queries
  7. Authentification
  8. Déploiement
  9. Structure du projet

Architecture

Client → Nginx(:443) → Sogoway(:8080) → Sogoms-* → MariaDB
                              ↓
                        Unix Sockets
                     /run/sogoms-*.sock

Flux de données

  1. Client envoie requête HTTPS vers Nginx
  2. Nginx route /api/* vers sogoway:8080
  3. Sogoway identifie l'app par hostname, valide JWT, route vers le bon service
  4. Sogoms-db exécute les requêtes SQL
  5. Sogoms-logs enregistre événements et erreurs

Principes

  • Modularité : 1 feature = 1 binaire Go
  • Configuration YAML : requêtes SQL externalisées, pas de recompilation
  • Multi-tenant : isolation par user_id, filtrage configurable par rôle
  • Supervision : sogoctl gère le cycle de vie des services

Services

Binaire Rôle Port/Socket
sogoctl Superviseur PID 1, health checks, restart auto -
sogoway Gateway HTTP, auth JWT, routing CRUD TCP :8080
sogoms-db Accès MariaDB, pool par application /run/sogoms-db.1.sock
sogoms-logs Logging centralisé, rotation auto /run/sogoms-logs.1.sock
sogoms-smtp Envoi d'emails, templates YAML /run/sogoms-smtp.1.sock

sogoctl (Superviseur)

  • Démarre les services dans l'ordre des dépendances
  • Health checks périodiques (socket ou HTTP)
  • Redémarrage automatique en cas de crash
  • Arrêt gracieux sur SIGTERM/SIGINT
# config/sogoctl.yaml
supervisor:
  health_interval: 10s
  restart_delay: 2s
  max_restarts: 5

services:
  sogoms-logs:
    binary: /opt/sogoms/bin/sogoms-logs
    args: ["-config", "/config", "-socket", "/run/sogoms-logs.1.sock"]
    health_socket: /run/sogoms-logs.1.sock

  sogoms-db:
    binary: /opt/sogoms/bin/sogoms-db
    args: ["-config", "/config", "-socket", "/run/sogoms-db.1.sock"]
    health_socket: /run/sogoms-db.1.sock
    depends_on: [sogoms-logs]

  sogoway:
    binary: /opt/sogoms/bin/sogoway
    args: ["-config", "/config", "-port", "8080"]
    health_url: http://localhost:8080/health
    depends_on: [sogoms-db, sogoms-logs]

sogoway (Gateway HTTP)

  • Routing par hostname → charge la config de l'app
  • Authentification JWT (HS256)
  • CRUD générique paramétré par YAML
  • Logging des événements (login, register)

sogoms-db (Base de données)

Actions disponibles :

  • query : SELECT multi-résultats
  • query_one : SELECT un résultat
  • insert : INSERT, retourne insert_id
  • update : UPDATE, retourne affected_rows
  • delete : DELETE, retourne affected_rows
  • health : ping DB

sogoms-logs (Logging)

Actions disponibles :

  • log_event : événement applicatif (login, register, etc.)
  • log_error : erreur avec niveau (error, warn, info)
  • health : statut OK

Fichiers générés : /var/log/sogoms/{app}-{YYYYMMDD}-{type}.log

Format : JSON, une ligne par entrée

Rotation : suppression automatique des fichiers > 30 jours (configurable)

sogoms-smtp (Emails)

Actions disponibles :

  • send : envoi email simple (to, subject, body, body_html)
  • send_template : envoi avec template YAML
  • send_bulk : envoi en masse (tableau de destinataires)
  • health : statut OK

Configuration SMTP dans config/routes/{app}.yaml :

smtp:
  host: mail.example.com
  port: 587
  user: noreply@example.com
  password_file: /secrets/{app}_smtp_pass
  from: noreply@example.com
  from_name: Mon App
  tls: false  # false = STARTTLS (587), true = TLS (465)

Templates dans config/emails/{app}/*.yaml :

subject: "Bienvenue {{.Name}} !"
body: |
  Bonjour {{.Name}},
  Bienvenue sur notre plateforme.
body_html: |
  <h1>Bienvenue {{.Name}} !</h1>
  <p>Bienvenue sur notre plateforme.</p>

Communication IPC

Protocole Unix socket avec messages JSON length-prefixed :

[4 bytes: longueur BigEndian] [payload JSON]

Request

{
  "id": "req_20251216123456.000000",
  "action": "query",
  "params": {
    "app_id": "prokov",
    "query": "SELECT * FROM users WHERE id = ?",
    "args": [1]
  }
}

Response (succès)

{
  "id": "req_...",
  "status": "success",
  "result": { ... }
}

Response (erreur)

{
  "id": "req_...",
  "status": "error",
  "error": {
    "code": "DB_ERROR",
    "message": "connection refused"
  }
}

Configuration

Structure

config/
├── sogoctl.yaml              # Superviseur
├── routes/
│   └── prokov.yaml           # Config app (DB, auth, routes)
└── queries/
    └── prokov/
        ├── auth.yaml         # Requêtes authentification
        ├── projects.yaml     # CRUD projects
        ├── tasks.yaml        # CRUD tasks
        ├── tags.yaml         # CRUD tags
        └── statuses.yaml     # CRUD statuses

Config application (routes/prokov.yaml)

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

hosts:
  - prokov.unikoffice.com
  - prokov.sogoms.com

database:
  host: 13.23.33.4
  port: 3306
  user: prokov_user
  password_file: /secrets/prokov_db_pass
  name: prokov

auth:
  jwt_secret_file: /secrets/prokov_jwt_secret
  jwt_expiry: 24h

logs:
  retention_days: 30

API REST

Authentification

Méthode Endpoint Auth Description
POST /api/auth/register Non Inscription
POST /api/auth/login Non Connexion
POST /api/auth/logout Oui Déconnexion
GET /api/auth/me Oui User courant

Login - Réponse enrichie

{
  "success": true,
  "message": "Connexion réussie",
  "data": {
    "token": "eyJ...",
    "user": { "id": 1, "email": "...", "name": "..." },
    "projects": [...],
    "tasks": [...],
    "tags": [...],
    "statuses": [...]
  }
}

CRUD Générique

Méthode Endpoint Action
GET /api/{resource} Liste
GET /api/{resource}/{id} Détail
POST /api/{resource} Création
PUT /api/{resource}/{id} Modification
DELETE /api/{resource}/{id} Suppression

Resources disponibles : projects, tasks, tags, statuses

Réponses standardisées

Succès :

{
  "success": true,
  "message": "Created",
  "data": { "insert_id": 123 }
}

Erreur :

{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Token expired"
  }
}

Système de Queries

Les requêtes SQL sont externalisées dans des fichiers YAML pour éviter la recompilation.

Structure Read (list/show)

list:
  query: >
    SELECT id, name, description FROM projects
  filters:
    default: "user_id = :user_id"
    admin: ""
  order: "position ASC"

show:
  query: >
    SELECT id, name, description FROM projects WHERE id = :id
  filters:
    default: "user_id = :user_id"
    admin: ""

Structure CUD (create/update/delete)

create:
  table: projects
  fields:
    - user_id
    - name
    - description
    - position

update:
  table: projects
  fields:
    - name
    - description
    - position
  filters:
    default: "user_id = :user_id"
    admin: ""

delete:
  table: projects
  filters:
    default: "user_id = :user_id"
    admin: ""

Placeholders

  • :user_id → ID utilisateur depuis JWT
  • :id → ID ressource depuis URL
  • :project_id → ID projet (pour filtres)

Filtres par rôle

Le filtre appliqué dépend du rôle de l'utilisateur :

  • default : utilisateur standard, filtré par user_id
  • admin : pas de filtre, voit tout

Authentification

JWT (JSON Web Token)

  • Algorithme : HS256
  • Expiration : configurable (défaut 24h)
  • Secret : stocké dans fichier (/secrets/{app}_jwt_secret)

Payload JWT

{
  "sub": 1,
  "email": "user@example.com",
  "name": "User Name",
  "app": "prokov",
  "exp": 1765959278,
  "iat": 1765872878
}

Header HTTP

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Sécurité

  • Passwords hashés avec bcrypt
  • JWT stateless (pas de stockage serveur)
  • Secrets dans fichiers séparés (pas dans YAML)
  • Filtrage user_id automatique sur toutes les requêtes CRUD

Déploiement

Script deploy.sh

./deploy.sh

Étapes :

  1. Build des binaires (linux/amd64)
  2. Création des archives tar.gz
  3. Copie vers jump server (IN3)
  4. Déploiement dans container Incus (gw3)
  5. Backup local des archives
  6. Redémarrage automatique de sogoctl

Cible

  • Jump host : IN3 (195.154.80.116)
  • Container : gw3 (Alpine, 13.23.33.5)
  • Binaires : /opt/sogoms/bin/
  • Config : /config/
  • Secrets : /secrets/
  • Logs : /var/log/sogoms/

Commandes manuelles sur gw3

# Voir les logs
tail -f /var/log/sogoms/sogoctl.log

# Lister les processus
pgrep -la sogo

# Redémarrer
pkill -9 sogo && /opt/sogoms/bin/sogoctl &

Structure du projet

sogoms/
├── cmd/
│   ├── sogoctl/main.go           # Superviseur
│   ├── sogoway/main.go           # Gateway HTTP
│   └── sogoms/
│       ├── db/main.go            # Microservice DB
│       ├── logs/main.go          # Microservice Logs
│       └── smtp/main.go          # Microservice SMTP
├── internal/
│   ├── protocol/
│   │   ├── message.go            # Structs Request/Response
│   │   ├── server.go             # Serveur Unix socket
│   │   └── client.go             # Client + Pool connexions
│   ├── config/
│   │   └── config.go             # Registry, Queries, CUD
│   ├── auth/
│   │   ├── jwt.go                # Génération/validation JWT
│   │   └── password.go           # Hash bcrypt
│   └── version/
│       └── version.go            # Version, BuildTime
├── config/
│   ├── sogoctl.yaml
│   ├── routes/
│   │   └── prokov.yaml           # Config app (DB, auth, SMTP)
│   ├── queries/
│   │   └── prokov/
│   │       ├── auth.yaml
│   │       ├── projects.yaml
│   │       ├── tasks.yaml
│   │       ├── tags.yaml
│   │       └── statuses.yaml
│   └── emails/
│       └── prokov/
│           ├── welcome.yaml
│           ├── password_reset.yaml
│           ├── task_assigned.yaml
│           └── tasks_today.yaml
├── clients/
│   └── prokov.sql                # Schéma DB
├── bin/                          # Binaires compilés
├── deploy.sh                     # Script déploiement
├── VERSION                       # Numéro de version
├── go.mod
├── go.sum
├── README.md
├── CLAUDE.md                     # Instructions Claude Code
├── DOCTECH.md                    # Documentation technique
└── TODO.md                       # Roadmap

Dépendances Go

go 1.24.0

github.com/go-sql-driver/mysql v1.9.3
gopkg.in/yaml.v3 v3.0.1
golang.org/x/crypto v0.46.0

Roadmap

Services planifiés

Phase Service Description
11 sogoms-crypt Chiffrement/déchiffrement données sensibles (AES-256-GCM)
12b sogoms-imap Lecture boîtes email (IMAP)
12c sogoms-mailproc Traitement emails (règles, webhooks)
13 sogoms-cron Tâches planifiées (format cron standard)
14 sogoms-push Push temps réel via MQTT (Mosquitto)
15 sogoms-schema Génération d'API depuis schéma YAML

Vision Phase 15 : Schema-Driven API

# config/schema/monapp.yaml - 1 fichier = 1 API complète
tables:
  users:
    fields:
      id: { type: int, primary: true, auto: true }
      email: { type: string, unique: true, auth: login }
      password: { type: string, auth: password, hidden: true }

  projects:
    fields:
      id: { type: int, primary: true, auto: true }
      user_id: { type: int, foreign: users.id, filter: owner }
      name: { type: string, required: true }
    crud: [list, show, create, update, delete]

Génère automatiquement : routes, queries, validation, filtres user_id, auth.

Hors scope V1

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