Phase 13 : sogoms-cron
- Jobs planifiés avec schedule cron standard
- Types: query_email, http, service
- Actions: list, trigger, status
Phase 16 : Réorganisation config/apps/{app}/
- Tous les fichiers d'une app dans un seul dossier
- Migration prokov vers nouvelle structure
Phase 17 : sogoms-admin
- Interface web d'administration (Go templates + htmx)
- Auth sessions cookies signées HMAC-SHA256
- Rôles super_admin / app_admin avec permissions
Phase 19 : Création d'app via Admin UI
- Formulaire création app avec config DB/auth
- Bouton "Scanner la base" : introspection + schema.yaml
- Rechargement automatique sogoway via SIGHUP
Infrastructure :
- sogoctl : socket de contrôle /run/sogoctl.sock
- sogoway : reload config sur SIGHUP sans restart
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
689 lines
17 KiB
Markdown
689 lines
17 KiB
Markdown
# 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](#architecture)
|
|
2. [Services](#services)
|
|
3. [Communication IPC](#communication-ipc)
|
|
4. [Configuration](#configuration)
|
|
5. [API REST](#api-rest)
|
|
6. [Système de Queries](#système-de-queries)
|
|
7. [Authentification](#authentification)
|
|
8. [Déploiement](#déploiement)
|
|
9. [Structure du projet](#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` |
|
|
| `sogoms-cron` | Tâches planifiées, jobs périodiques | `/run/sogoms-cron.1.sock` |
|
|
| `sogoms-admin` | Interface web d'administration | TCP :9000 |
|
|
|
|
### 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
|
|
- **Socket de contrôle** `/run/sogoctl.sock` pour commandes runtime :
|
|
- `reload <service>` : envoie SIGHUP au service (rechargement config)
|
|
- `status` : affiche l'état des services
|
|
|
|
```yaml
|
|
# 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)
|
|
- **Rechargement à chaud** : SIGHUP recharge registry + JWT sans restart
|
|
|
|
### 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` :
|
|
```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` :
|
|
```yaml
|
|
subject: "Bienvenue {{.Name}} !"
|
|
body: |
|
|
Bonjour {{.Name}},
|
|
Bienvenue sur notre plateforme.
|
|
body_html: |
|
|
<h1>Bienvenue {{.Name}} !</h1>
|
|
<p>Bienvenue sur notre plateforme.</p>
|
|
```
|
|
|
|
### sogoms-cron (Tâches planifiées)
|
|
|
|
Exécute des jobs périodiques définis en YAML avec support cron standard.
|
|
|
|
Actions disponibles :
|
|
- `list` : liste les jobs configurés avec prochain run
|
|
- `trigger` : déclenche un job manuellement
|
|
- `status` : historique des dernières exécutions
|
|
- `health` : statut OK
|
|
|
|
Types de jobs :
|
|
- `query_email` : requête DB + envoi email groupé par utilisateur
|
|
- `http` : appel HTTP (GET/POST) vers endpoint interne ou externe
|
|
- `service` : appel service interne (sogoms-db, sogoms-smtp, etc.)
|
|
|
|
Configuration dans `config/apps/{app}/cron.yaml` :
|
|
```yaml
|
|
timezone: Europe/Paris
|
|
retry:
|
|
max_attempts: 3
|
|
delay: 5m
|
|
history_days: 7
|
|
|
|
jobs:
|
|
tasks_today:
|
|
schedule: "0 8 * * 1-5" # 8h00 lun-ven
|
|
type: query_email
|
|
query: |
|
|
SELECT u.id AS user_id, u.email, u.name AS user_name,
|
|
t.title, p.name AS project_name, s.name AS status_name
|
|
FROM users u
|
|
INNER JOIN tasks t ON t.user_id = u.id
|
|
LEFT JOIN projects p ON t.project_id = p.id
|
|
LEFT JOIN statuses s ON t.status_id = s.id
|
|
WHERE t.date_end <= CURDATE()
|
|
group_by: user_id
|
|
template: tasks_today
|
|
enabled: true
|
|
```
|
|
|
|
Format cron : `minute heure jour mois jour_semaine`
|
|
- `0 8 * * 1-5` : 8h00 du lundi au vendredi
|
|
- `*/15 * * * *` : toutes les 15 minutes
|
|
- `0 9 1 * *` : 9h00 le premier de chaque mois
|
|
|
|
### sogoms-admin (Interface web)
|
|
|
|
Interface d'administration web pour gérer les applications SOGOMS.
|
|
|
|
**Rôles :**
|
|
- `super_admin` : accès global à toutes les apps et services
|
|
- `app_admin` : accès limité aux apps assignées avec permissions fines
|
|
|
|
**Stack :**
|
|
- Backend : Go net/http
|
|
- Frontend : Go templates + htmx + Pico.css (embarqués via go:embed)
|
|
- Auth : sessions cookies signées (HMAC-SHA256)
|
|
|
|
**Sécurité :**
|
|
- Passwords : bcrypt cost=12
|
|
- Sessions : Cookie HttpOnly + Secure + SameSite=Strict
|
|
- CSRF : Token par session
|
|
- Rate limiting : 5 tentatives/min par IP
|
|
|
|
**Routes :**
|
|
- `GET /admin/login` : page de connexion
|
|
- `POST /admin/login` : authentification
|
|
- `GET /admin/` : dashboard principal
|
|
- `POST /admin/logout` : déconnexion
|
|
- `GET /admin/api/apps` : liste apps (htmx partial)
|
|
- `GET /admin/api/services/health` : statut services (htmx partial)
|
|
|
|
**Configuration :**
|
|
```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
|
|
|
|
- username: client1
|
|
password_hash: "$2a$12$..."
|
|
role: app_admin
|
|
apps: [prokov]
|
|
permissions:
|
|
- schema:read
|
|
- queries:read
|
|
- cron:read
|
|
- logs:read
|
|
```
|
|
|
|
**Permissions disponibles :**
|
|
- `schema:read/write/upload` : gestion schema
|
|
- `queries:read/write` : requêtes SQL
|
|
- `emails:read/write` : templates email
|
|
- `cron:read/write/trigger` : jobs cron
|
|
- `logs:read` : consultation logs
|
|
- `db:introspect` : introspection DB
|
|
- `*` : toutes (super_admin)
|
|
|
|
**Accès externe :** `admin.sogoms.com` via Nginx → :9000
|
|
|
|
---
|
|
|
|
## Communication IPC
|
|
|
|
Protocole Unix socket avec messages JSON length-prefixed :
|
|
|
|
```
|
|
[4 bytes: longueur BigEndian] [payload JSON]
|
|
```
|
|
|
|
### Request
|
|
|
|
```json
|
|
{
|
|
"id": "req_20251216123456.000000",
|
|
"action": "query",
|
|
"params": {
|
|
"app_id": "prokov",
|
|
"query": "SELECT * FROM users WHERE id = ?",
|
|
"args": [1]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Response (succès)
|
|
|
|
```json
|
|
{
|
|
"id": "req_...",
|
|
"status": "success",
|
|
"result": { ... }
|
|
}
|
|
```
|
|
|
|
### Response (erreur)
|
|
|
|
```json
|
|
{
|
|
"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)
|
|
|
|
```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
|
|
|
|
```json
|
|
{
|
|
"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 :**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Created",
|
|
"data": { "insert_id": 123 }
|
|
}
|
|
```
|
|
|
|
**Erreur :**
|
|
```json
|
|
{
|
|
"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)
|
|
|
|
```yaml
|
|
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)
|
|
|
|
```yaml
|
|
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
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
```bash
|
|
./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
|
|
|
|
```bash
|
|
# 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
|
|
│ ├── cron/main.go # Microservice Cron
|
|
│ └── admin/ # Interface web admin
|
|
│ ├── main.go
|
|
│ ├── handlers.go
|
|
│ ├── middleware.go
|
|
│ ├── session.go
|
|
│ ├── services.go
|
|
│ └── templates/
|
|
├── internal/
|
|
│ ├── protocol/
|
|
│ │ ├── message.go # Structs Request/Response
|
|
│ │ ├── server.go # Serveur Unix socket
|
|
│ │ └── client.go # Client + Pool connexions
|
|
│ ├── config/
|
|
│ │ └── config.go # Registry, Queries, CUD
|
|
│ ├── cron/
|
|
│ │ └── scheduler.go # Parser cron, calcul next run
|
|
│ ├── auth/
|
|
│ │ ├── jwt.go # Génération/validation JWT
|
|
│ │ └── password.go # Hash bcrypt
|
|
│ ├── admin/
|
|
│ │ ├── config.go # Chargement admin_users.yaml
|
|
│ │ ├── permissions.go # Vérification droits
|
|
│ │ └── audit.go # Logging actions
|
|
│ └── version/
|
|
│ └── version.go # Version, BuildTime
|
|
├── config/
|
|
│ ├── sogoctl.yaml
|
|
│ └── apps/
|
|
│ └── prokov/
|
|
│ ├── app.yaml # Config app (DB, auth, SMTP)
|
|
│ ├── schema.yaml # Schema DB généré
|
|
│ ├── cron.yaml # Jobs planifiés
|
|
│ ├── queries/ # Requêtes SQL
|
|
│ │ ├── auth.yaml
|
|
│ │ ├── projects.yaml
|
|
│ │ └── ...
|
|
│ └── emails/ # Templates email
|
|
│ ├── welcome.yaml
|
|
│ └── tasks_today.yaml
|
|
├── 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
|
|
|
|
```yaml
|
|
# 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)
|