ligbox-ops-platform/specs/004-onboard-funnel-events/contracts/webhook-funnel-events.md
Ligbox Spec Hub 3a2c64834b Initial import: ligbox-ops-platform + specs + LAPTOP + obsidian merge (CT130)
Source: VM122 /opt + obsidian-infra + LAPTOP
Hub: CT130 spec-hub 10.10.10.130
2026-06-19 17:26:41 +00:00

2.8 KiB

Contract: Webhook Funil Onboarding

Endpoint: POST /api/v1/webhooks/onboard (inalterado — feature 001)

Auth: Header X-Webhook-Secret

Eventos adicionais (004)

Todos usam o mesmo WebhookPayload:

{
  "event": "<event_type>",
  "domain": "exemplo.com",
  "session_id": "uuid-da-sessao",
  "data": { }
}

onboarding.started

{
  "event": "onboarding.started",
  "domain": "exemplo.com",
  "session_id": "abc-123",
  "data": { "step": "validate-domain" }
}

Ticket: não cria.


domain.validated

{
  "event": "domain.validated",
  "domain": "exemplo.com",
  "session_id": "abc-123",
  "data": {
    "carbonio_domain_exists": false,
    "cloudflare_auto_dns": true,
    "mail_aliases": ["www"]
  }
}

Ticket: não cria.


dns.applied

{
  "event": "dns.applied",
  "domain": "exemplo.com",
  "session_id": "abc-123",
  "data": {
    "records_applied": 5,
    "verification_ready": true
  }
}

Ticket: não cria.


infra.synced

{
  "event": "infra.synced",
  "domain": "exemplo.com",
  "session_id": "abc-123",
  "data": {
    "traefik": "ok",
    "cert": "ok",
    "nginx_vhost": "ok"
  }
}

Ticket: não cria.


onboarding.completed

{
  "event": "onboarding.completed",
  "domain": "exemplo.com",
  "session_id": "abc-123",
  "data": {
    "email": "admin@exemplo.com",
    "account_verified": true,
    "infra_status": "ok"
  }
}

Ticket: actualiza ticket existente (nota ready_for_ops); não cria novo.


onboarding.failed

{
  "event": "onboarding.failed",
  "domain": "exemplo.com",
  "session_id": "abc-123",
  "data": {
    "step": "create_account",
    "error": "CarbonioError message",
    "http_status": 400
  }
}

Ticket: cria ticket open prioridade alta (subject [onboarding.failed] dominio.com).


Response (200 OK)

{
  "status": "accepted",
  "event_id": 42,
  "ticket_id": null,
  "duplicate": false
}

Idempotência

Chave: (event, session_id, domain) — duplicate=true, ticket_id existente se aplicável.

API consulta (Ops)

GET /api/v1/onboard/funnel

{
  "window_hours": 48,
  "stages": {
    "started": 3,
    "domain_validated": 2,
    "dns_applied": 2,
    "account_created": 1,
    "infra_synced": 1,
    "completed": 1,
    "failed": 0
  },
  "active_sessions": [
    {
      "session_id": "abc-123",
      "domain": "exemplo.com",
      "current_stage": "dns_applied",
      "last_event_at": "2026-06-08T18:00:00Z",
      "ticket_id": 5
    }
  ]
}

GET /api/v1/onboard/sessions/{session_id}/timeline

{
  "session_id": "abc-123",
  "domain": "exemplo.com",
  "events": [
    { "event_type": "onboarding.started", "created_at": "...", "data": {} },
    { "event_type": "domain.validated", "created_at": "...", "data": {} }
  ]
}