Data Model: Webhook VM112 → Ops Platform
Webhook Payload (request body)
| Campo |
Tipo |
Obrigatório |
Descrição |
event |
string |
sim |
Tipo: account.created, domain.validated, dns.applied, onboarding.completed, onboarding.failed |
domain |
string |
sim* |
Domínio normalizado lowercase (*opcional para alguns eventos futuros) |
session_id |
string |
não |
ID sessão onboarding (X-Onboarding-Session) |
data |
object |
não |
Metadados específicos do evento |
data para account.created
| Campo |
Tipo |
Descrição |
email |
string |
Email criado (admin@dominio.com) |
account_verified |
boolean |
Resultado carbonio.account_exists |
needs_review |
boolean |
Inverso de verified ou flag explícita |
dns_mode |
string |
Modo DNS indicado no onboarding |
mail_aliases |
string[] |
Aliases configurados (opcional) |
Ops Platform — entidades existentes
webhook_events
| Coluna |
Tipo |
Notas |
| id |
INTEGER PK |
auto |
| event_type |
TEXT |
ex: account.created |
| source |
TEXT |
vm112-onboard |
| payload |
TEXT |
JSON serializado |
| created_at |
TEXT ISO8601 UTC |
|
Dedup key (lógica): event_type + JSON_EXTRACT(payload,'$.session_id') + JSON_EXTRACT(payload,'$.domain')
tickets
| Coluna |
Tipo |
Notas |
| id |
INTEGER PK |
auto |
| tenant_id |
INTEGER |
1 = VM112 |
| subject |
TEXT |
[account.created] dominio.com — email |
| status |
TEXT |
open default |
| payload |
TEXT |
JSON do evento |
| created_at |
TEXT ISO8601 UTC |
|
tenants (pré-existente)
| id |
name |
ip |
role |
| 1 |
VM112 Ligbox Onboard |
10.10.10.112 |
onboarding_portal |
Portal — configuração (.env)
| Variável |
Exemplo |
Descrição |
OPS_WEBHOOK_URL |
http://10.10.10.122:8080/api/v1/webhooks/onboard |
Endpoint receptor |
OPS_WEBHOOK_SECRET |
(secret) |
Igual a WEBHOOK_SECRET em VM122 |
OPS_WEBHOOK_ENABLED |
true |
Kill switch sem redeploy |
State transitions
onboarding.create_account
→ [portal] carbonio.create_account OK
→ [portal] ops_webhook.emit("account.created") [background]
→ [ops] validate secret
→ [ops] check dedup
→ [ops] INSERT webhook_events
→ [ops] INSERT tickets (se account.created e não duplicado)
→ [ops] LPUSH ops:events redis
→ [ops] return {"accepted": true}
Response
{"accepted": true, "event": "account.created"}
Erros:
401 — secret inválido
422 — payload inválido (pydantic)