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

183 lines
2.8 KiB
Markdown

# 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`:
```json
{
"event": "<event_type>",
"domain": "exemplo.com",
"session_id": "uuid-da-sessao",
"data": { }
}
```
### onboarding.started
```json
{
"event": "onboarding.started",
"domain": "exemplo.com",
"session_id": "abc-123",
"data": { "step": "validate-domain" }
}
```
**Ticket**: não cria.
---
### domain.validated
```json
{
"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
```json
{
"event": "dns.applied",
"domain": "exemplo.com",
"session_id": "abc-123",
"data": {
"records_applied": 5,
"verification_ready": true
}
}
```
**Ticket**: não cria.
---
### infra.synced
```json
{
"event": "infra.synced",
"domain": "exemplo.com",
"session_id": "abc-123",
"data": {
"traefik": "ok",
"cert": "ok",
"nginx_vhost": "ok"
}
}
```
**Ticket**: não cria.
---
### onboarding.completed
```json
{
"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
```json
{
"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)
```json
{
"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
```json
{
"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
```json
{
"session_id": "abc-123",
"domain": "exemplo.com",
"events": [
{ "event_type": "onboarding.started", "created_at": "...", "data": {} },
{ "event_type": "domain.validated", "created_at": "...", "data": {} }
]
}
```