Padrao Gatilho → Condicao → Acao
Trigger (event, scheduled, ou webhook)
↓
Condition (logic AND/OR, com rules sobre user.*, event.*)
↓
Action (uma ou mais, executadas sequencialmente)
Triggers (3 tipos)
1. event
Disparado por eventos da plataforma via emitAutomationEvent() em after().
{ "type": "event", "config": { "eventName": "lesson_completed", "filters": {} } }
Eventos suportados: lesson_completed, module_completed, course_completed, quiz_submitted, enrollment_created, enrollment_completed, forum_post_created, forum_reply_created, grade_posted, announcement_created, live_class_started, student_inactive, tag_added_to_user, tag_removed_from_user, webhook_received, scheduled_trigger.
2. scheduled
Cron-based.
{
"type": "scheduled",
"config": {
"mode": "interval|daily|weekly|cron",
"hours": 24,
"time": "08:00",
"timezone": "America/Sao_Paulo"
}
}
Processado por GET /api/cron/automations (CRON_SECRET).
3. webhook
Endpoint publico autenticado por token 64-char hex.
URL: /api/automations/webhook/[token]
GET → health check
POST → triggers automation (body JSON virara event.data)
Conditions
{
"logic": "and",
"rules": [
{ "field": "user.role", "operator": "eq", "value": "student" },
{ "field": "event.score", "operator": "gte", "value": 80 }
]
}
Operators: eq, neq, gt, gte, lt, lte, contains, not_contains, in, not_in.
Fields acessiveis:
user.*— id, name, email, role, tagsevent.*— campos do evento (courseId, score, lessonTitle, etc)
Nested groups (AND/OR) sao suportados.
Actions (8 tipos)
| Action | Funcao |
|---|---|
| send_notification | In-app notification (trigger_user ou users_with_tag) |
| add_tag | Adicionar UserTag |
| remove_tag | Remover UserTag |
| create_announcement | Cria Announcement + notifica alunos (curso ou tenant) |
| send_webhook | POST/PUT para URL externa (com SSRF prevention) |
| send_web_request | GET/POST/PUT/DELETE para API externa |
| enroll_user | Matricula trigger_user em curso |
| trigger_automation | Encadeia outra (max depth 5) |
Template interpolation
Strings em actions suportam {{placeholders}}:
{{user.name}},{{user.email}},{{user.role}}{{event.courseId}},{{event.score}},{{event.lessonTitle}}
Seguranca
- Tenant isolation: todas as queries filtram por tenantId. Automacao de um tenant NUNCA executa para usuario de outro.
- SSRF prevention:
url-validator.tsbloqueia IPs privados, localhost, metadata endpoints (169.254.169.254). IPv4 + IPv6. - HTTP timeout: 10s via AbortController.
- Webhook token: 64-char hex, rotacionavel.
- Chain depth: max 5 niveis de trigger_automation recursivo.
- Rate limit: maxRunsPerHour/maxRunsPerDay por automacao (Redis INCR, fallback DB count).
Exemplo: notificar pai quando aluno menor inativo 5 dias
{
"name": "Alerta inatividade — menores",
"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}} inativo ha {{event.inactiveDays}} dias",
"message": "Estimulamos um login. Acesse [link]."
}
}
]
}
UI
/institution/automations:
- Lista com filtros (status, trigger type), toggle, search
- Wizard 4 steps (Trigger → Conditions → Actions → Review)
- Historico de runs com rows expandiveis (status, duration, actionResults JSON)