Schéma Déclencheur → Condition → Action
Trigger (event, scheduled, ou webhook)
↓
Condition (logique AND/OR, avec règles sur user.*, event.*)
↓
Action (une ou plusieurs, exécutées séquentiellement)
Déclencheurs (3 types)
1. event
Déclenché par des événements de la plateforme via emitAutomationEvent() dans after().
{ "type": "event", "config": { "eventName": "lesson_completed", "filters": {} } }
Les 21 événements supportés : lesson_completed, module_completed, course_completed, quiz_submitted, assignment_submitted, enrollment_created, enrollment_completed, forum_post_created, forum_reply_created, grade_posted, announcement_created, live_class_scheduled, live_class_started, student_inactive, tag_added_to_user, tag_removed_from_user, webhook_received, scheduled_trigger, et les événements de gamification badge_earned, level_up, contest_ended.
2. scheduled
Basé sur des crons.
{
"type": "scheduled",
"config": {
"mode": "interval|daily|weekly|cron",
"hours": 24,
"time": "08:00",
"timezone": "America/Sao_Paulo"
}
}
Traité par GET /api/cron/automations (CRON_SECRET).
3. webhook
Point de terminaison public authentifié par un token hexadécimal de 64 caractères.
URL: /api/automations/webhook/[token]
GET → health check
POST → déclenche l'automatisation (le body JSON devient event.data)
Conditions
{
"logic": "and",
"rules": [
{ "field": "user.role", "operator": "eq", "value": "student" },
{ "field": "event.score", "operator": "gte", "value": 80 }
]
}
Opérateurs : eq, neq, gt, gte, lt, lte, contains, not_contains, in, not_in.
Champs accessibles :
user.*— id, name, email, role, tagsevent.*— champs de l'événement (courseId, score, lessonTitle, etc.)
Les groupes imbriqués (AND/OR) sont supportés.
Actions (9 types)
| Action | Fonction |
|---|---|
| send_notification | Notification in-app (trigger_user ou users_with_tag) |
| add_tag | Ajouter un UserTag |
| remove_tag | Supprimer un UserTag |
| create_announcement | Crée une annonce + notifie les apprenants (cours ou tenant) |
| send_webhook | POST/PUT vers une URL externe (avec prévention SSRF) |
| send_web_request | GET/POST/PUT/DELETE vers une API externe |
| enroll_user | Inscrit trigger_user à un cours |
| trigger_automation | Enchaîne une autre automatisation (profondeur max 5) |
| send_email | E-mail via le service institutionnel (SMTP/Resend/SendGrid), par slug de template ou subject+HTML inline ; cible trigger_user, users_with_tag, course_students ou adresse personnalisée |
Interpolation de templates
Les chaînes dans les actions supportent les {{placeholders}} :
{{user.name}},{{user.email}},{{user.role}}{{event.courseId}},{{event.score}},{{event.lessonTitle}}
Sécurité
- Isolation par tenant : toutes les requêtes filtrent par tenantId. L'automatisation d'un tenant n'est JAMAIS exécutée pour un utilisateur d'un autre tenant.
- Prévention SSRF :
url-validator.tsbloque les IP privées, localhost, les endpoints de métadonnées (169.254.169.254). IPv4 + IPv6. - Timeout HTTP : 10s via AbortController.
- Token webhook : hexadécimal 64 caractères, renouvelable.
- Profondeur de chaîne : max 5 niveaux de trigger_automation récursif.
- Rate limit : maxRunsPerHour/maxRunsPerDay par automatisation (Redis INCR, fallback DB count).
Exemple : notifier le parent lorsqu'un apprenant mineur est inactif depuis 5 jours
{
"name": "Alerte inactivité — mineurs",
"trigger": {
"type": "event",
"config": { "eventName": "student_inactive" }
},
"conditions": {
"logic": "and",
"rules": [
{ "field": "user.role", "operator": "eq", "value": "student" },
{ "field": "user.isMinor", "operator": "eq", "value": true },
{ "field": "event.inactiveDays", "operator": "gte", "value": 5 }
]
},
"actions": [
{
"type": "send_notification",
"config": {
"recipient": "users_with_tag",
"tag": "parent_of_{{user.id}}",
"title": "{{user.name}} inactif depuis {{event.inactiveDays}} jours",
"message": "Nous l'encourageons à se connecter. Accédez à [lien]."
}
}
]
}
Interface
/institution/automations :
- Liste avec filtres (statut, type de déclencheur), toggle, recherche
- Wizard en 4 étapes (Déclencheur → Conditions → Actions → Récapitulatif)
- Historique des exécutions avec lignes dépliables (statut, durée, actionResults JSON)