ligbox-ops-platform/specs/010-admin-domain-validation/spec.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

17 KiB
Raw Blame History

SPEC — Integração Validação Admin Domínios Virtuais (Wizard VM112 + Desk VM122)

Versão: 1.0
Data: 2026-06-12
Autor: Roger / Cursor DevOps
Estado: 📋 PLANEAMENTO (correcção VM112 concluída)
Depende de: SPEC-CORRECAO-ADMIN-DOMINIOS-VIRTUAIS.md


1. Objectivo

Integrar a validação e provisionamento admin Carbonio (porta :6071, redirect /admin, certs SSL) no:

  1. Wizard VM112 (/opt/ligbox-wizard/) — onboarding automático por domínio virtual
  2. VM122 Ligbox Ops (ligbox-ops-platform) — Desk, tickets, timeline, auditoria

Problema actual: validação admin existe em scripts offline (admin-login-check/) mas não no wizard API nem no Desk.


2. Contexto — dois conceitos de «admin»

Conceito URL Onde vive hoje
Painel delegado wizard https://onboard.ligbox.com.br/admin SPA DomainAdmin.jsx + /api/domain-admin/*
Carbonio Admin Console https://mail.{dominio}/admin:6071/static/login/ nginx VM112 + Carbonio auth

Esta spec trata exclusivamente do Carbonio Admin Console por domínio virtual.


3. Estado actual vs alvo

3.1 Wizard — infrastructure.py (6 checks hoje)

ID actual O que valida Admin?
carbonio_domain zmprov domínio existe
dns_mail MX/A públicos
haproxy_sni SNI CT114
traefik_router Router Traefik :443
cert_san LE mail-vm112-multi (webmail) (não :6071)
webmail_https GET :443

3.2 Novos checks admin (4 adicionais)

ID novo Label O que valida Severidade
admin_redirect_443 Admin redirect :443 GET /admin → 302 Location :6071/static/login/ P1
admin_cert_6071 Cert SSL admin :6071 CN/SAN = mail.{dominio} no cert nginx :6071 P1
admin_login_6071 Admin login :6071 E4 /zx/login/supported JSON 200; E6 config OK P1
admin_block_nginx Bloco nginx admin server block :6071 existe (admin ou .custom) P2

3.3 Estado alvo — 10 checks infra

carbonio_domain → dns_mail → haproxy_sni → traefik_router → cert_san → webmail_https
    → admin_block_nginx → admin_redirect_443 → admin_cert_6071 → admin_login_6071

ready: true quando todos P1 OK (P2 = warning, não bloqueia onboarding).


4. Wizard VM112 — desenho técnico

4.1 Novo módulo Python

Ficheiro: /opt/ligbox-wizard/backend/app/services/admin_domain_validation.py

# Funções principais (interface proposta)
def check_admin_redirect(mail_host: str) -> StepResult
def check_admin_cert_sni(mail_host: str) -> StepResult
def check_admin_login_flow(mail_host: str) -> StepResult
def check_admin_nginx_block(mail_host: str) -> StepResult
def provision_admin_infra(domain: str, mail_aliases: list[str] | None) -> ProvisionResult

Implementação interna:

Check Método
admin_redirect_443 httpx HEAD https://{mail_host}/admin → Location contém :6071/static/login/
admin_cert_6071 openssl s_client -connect 127.0.0.1:6071 -servername {host} ou leitura nginx ssl_certificate
admin_login_6071 Subprocess node check-admin-login-flow.mjs --host {mail_host} ou reimplementar E4/E6 em Python
admin_block_nginx grep server block em carbonio.admin + .custom

4.2 Alterações em infrastructure.py

get_status() — adicionar 4 steps após webmail_https:

steps.append(check_admin_block_nginx(all_hosts))
steps.append(check_admin_redirect_443(all_hosts))
steps.append(check_admin_cert_6071(all_hosts))
steps.append(check_admin_login_6071(all_hosts))

Payload de resposta (exemplo):

{
  "domain": "iofficebooks.com",
  "mail_host": "mail.iofficebooks.com",
  "steps": [
    {"id": "admin_redirect_443", "ok": true, "message": "302 → :6071/static/login/"},
    {"id": "admin_cert_6071", "ok": true, "message": "CN=mail.iofficebooks.com"},
    {"id": "admin_login_6071", "ok": true, "message": "E4 JSON 200, E6 domain OK"},
    {"id": "admin_block_nginx", "ok": true, "message": "bloco :6071 presente"}
  ],
  "admin_ready": true
}

provision() — novo step admin_infra após cert_san:

def do_admin_infra() -> str:
    # 1. sync-traefik-admin-certs.sh (se domínio usa cert Traefik)
    # 2. apply-admin-nginx-overrides.py --reload
    # 3. re-validar admin_redirect + admin_cert + admin_login

Ordem provision completa:

domain_site_layout → haproxy_sni → traefik_router → cert_san → admin_infra → (re-check all)

4.3 API routes (sem breaking changes)

Método Route Alteração
GET /api/onboarding/infrastructure/status/{domain} +4 steps admin
POST /api/onboarding/infrastructure/provision?step=admin_infra Novo step
POST /api/onboarding/infrastructure/provision Inclui admin_infra no fluxo completo

4.4 Frontend wizard (App.jsx / WizardProcessHub)

UI — secção «Infraestrutura admin» no painel de progresso:

Step UI Ícone OK Ícone fail Acção
Redirect /admin ⚠️ «Abrir admin» link
Certificado :6071 «Sincronizar cert» botão
Login admin «Diagnosticar» → activity log
Bloco nginx ⚠️ automático

Link pós-onboarding (Passo Concluído):

Admin do domínio: https://mail.{dominio}/admin
(credenciais: admin@{dominio})

4.5 Activity log — mensagens

[infra] admin_redirect_443: OK — 302 → mail.iofficebooks.com:6071/static/login/
[infra] admin_cert_6071: FAIL — CN=mail.diarissima.com (esperado mail.iofficebooks.com)
[infra] admin_infra: sync Traefik certs + apply nginx overrides
[infra] admin_login_6071: OK — E4/E6 validados

4.6 Configuração (.env / config.py)

# Novos settings
admin_check_scripts_dir: str = "/opt/ligbox-deploy/scripts/admin-login-check"
admin_nginx_apply_script: str = ".../apply-admin-nginx-overrides.py"
admin_traefik_sync_script: str = ".../sync-traefik-admin-certs.sh"
admin_canonical_url: str = "https://mail.ligbox.com.br:6071/static/login/"

4.7 Hook em POST /account/create

Após criar conta e auto-provision infra existente:

# onboarding.py — após provision infra
infra = infrastructure.provision(domain, mail_aliases=aliases)
if not infra["status"].get("admin_ready"):
    activity_log.warn(f"Admin infra incompleto: {domain}", source="infra")
    # Não bloquear cliente — emitir webhook infra.partial
ops_webhook.emit("infra.synced", domain, session_id, data={
    "steps": infra["status"]["steps"],
    "admin_ready": infra["status"].get("admin_ready"),
    "admin_url": f"https://mail.{domain}/admin",
})

5. VM122 Desk — desenho técnico

5.1 VM122 actual

Componente Path Estado
API ligbox-ops-platform/api/app/main.py running
Desk UI frontend/desk.ligbox.com.br
Webhook ingest POST /api/v1/webhooks/onboard
SQLite tenants, tickets, webhook_events

5.2 Novos eventos webhook (extend contract 001 + 004)

Event Emissor Quando Cria ticket?
infra.synced VM112 wizard Após provision infra completo Nota em ticket existente
admin.validation.failed VM112 wizard admin_ready=false pós-provision Sim (prioridade média)
admin.cert.expiring VM122 cron/worker Cert :6071 < 14 dias Sim (prioridade baixa)

Payload infra.synced (extendido):

{
  "event": "infra.synced",
  "domain": "iofficebooks.com",
  "session_id": "sess-abc123",
  "data": {
    "mail_host": "mail.iofficebooks.com",
    "admin_ready": true,
    "admin_url": "https://mail.iofficebooks.com/admin",
    "admin_url_canonical": "https://mail.ligbox.com.br:6071/static/login/",
    "steps": [
      {"id": "admin_redirect_443", "ok": true},
      {"id": "admin_cert_6071", "ok": true},
      {"id": "admin_login_6071", "ok": true}
    ],
    "provisioned_at": "2026-06-12T18:52:00Z"
  }
}

Payload admin.validation.failed:

{
  "event": "admin.validation.failed",
  "domain": "betinplace.com",
  "session_id": "sess-xyz",
  "data": {
    "failed_steps": ["admin_cert_6071"],
    "messages": ["CN mismatch: expected mail.betinplace.com"],
    "suggested_action": "Run sync-traefik-admin-certs.sh + apply-admin-nginx-overrides.py --reload"
  }
}

5.3 VM122 — alterações API

Ficheiro: api/app/routers/webhooks.py (ou equivalente)

# Novos handlers
EVENT_HANDLERS = {
    ...
    "infra.synced": handle_infra_synced,          # update ticket + timeline
    "admin.validation.failed": handle_admin_fail,  # create ticket priority=medium
}

Ficheiro: api/app/routers/desk.py — extend ticket detail

# GET /api/v1/desk/tickets/{id}
# + admin_status block quando domain conhecido:
{
  "admin_status": {
    "ready": true,
    "url": "https://mail.iofficebooks.com/admin",
    "last_check": "2026-06-12T18:52:00Z",
    "failed_steps": []
  }
}

5.4 VM122 — novo endpoint auditoria admin

GET /api/v1/infra/admin-status/{domain}

Resposta: proxy para VM112 GET /api/onboarding/infrastructure/status/{domain} filtrando steps admin, ou VM122 armazena último infra.synced.

Uso Desk: widget «Admin domínio» no detalhe do ticket.

5.5 VM122 Desk UI — telas

Tela 1: Ticket detalhe — secção «Admin domínio»

┌─────────────────────────────────────────────────┐
│ Admin Carbonio — iofficebooks.com               │
├─────────────────────────────────────────────────┤
│ URL: https://mail.iofficebooks.com/admin    [↗]  │
│ Redirect :443    ✅ 302 → :6071                  │
│ Cert :6071       ✅ CN=mail.iofficebooks.com     │
│ Login E4/E6      ✅                              │
│ Última validação: 2026-06-12 18:52 UTC          │
│ [Re-validar agora]  [Abrir admin]               │
└─────────────────────────────────────────────────┘

Tela 2: Dashboard Ops — widget «Admin domínios»

Domínio Admin OK Cert :6071 Último check
iofficebooks.com 12/06 18:52
betinplace.com 12/06 18:52
novo-cliente.com

Fonte: agregação webhook_events tipo infra.synced + admin.validation.failed.

Tela 3: Runbook Desk — «Admin ERR_CERT»

Passos automáticos sugeridos (link para runbook):

  1. Verificar Traefik tem cert para mail.{dominio}
  2. Correr sync-traefik-admin-certs.sh
  3. Correr apply-admin-nginx-overrides.py --reload
  4. Re-validar via wizard ou script E1E8

5.6 Processos Desk Support

Processo 1: Onboarding novo domínio (automático)

sequenceDiagram
    participant C as Cliente
    participant W as Wizard VM112
    participant C114 as Traefik CT114
    participant V112 as Carbonio VM112
    participant O as Ops VM122 Desk

    C->>W: validate-domain + create account
    W->>C114: provision SNI + router + cert :443
    W->>V112: cert_san + admin_infra
    Note over V112: sync Traefik certs + nginx overrides
    W->>W: validate admin_redirect + cert + login
    alt admin_ready=true
        W->>O: webhook infra.synced (admin_ready=true)
        O->>O: timeline + nota ticket
    else admin_ready=false
        W->>O: webhook admin.validation.failed
        O->>O: ticket prioridade média + runbook
    end
    W->>C: onboarding.completed + link /admin

Processo 2: Ticket manual «Admin não abre»

Passo Actor Acção
1 NOC Cliente reporta ERR_CERT ou 504 em mail.X/admin
2 Desk Abrir ticket; campo domínio preenchido
3 Desk GET /api/v1/infra/admin-status/{domain}
4 Técnico Se cert fail → sync Traefik + apply overrides
5 Técnico Se redirect fail → apply-admin-nginx-overrides.py
6 Técnico Se NAT fail → verificar pfSense :6071 → VM112
7 Desk Re-validar; fechar ticket com evidência curl

Processo 3: Renovação cert (preventivo)

Trigger Acção
Traefik renova LE (CT114) Cron VM112: sync-traefik-admin-certs.sh semanal
Cert < 14 dias VM122 emite admin.cert.expiring → ticket low priority
zmproxyconfgen executado Obrigatório zmproxyconfgen-ligbox

Processo 4: Novo domínio virtual (pós-onboarding)

Quando ops adiciona domínio manualmente (zmprov cd):

  1. Correr wizard infrastructure/provision?domain=X (ou script CLI)
  2. Inclui step admin_infra automaticamente
  3. Desk recebe infra.synced ou admin.validation.failed

6. Wire VM112 → VM122 (pré-requisitos)

6.1 Completar ops_webhook.py (VM112)

Ficheiro: /opt/ligbox-wizard/backend/app/services/ops_webhook.py

Adicionar em config.py:

ops_webhook_enabled: bool = False
ops_webhook_url: str = "http://10.10.10.122:8080/api/v1/webhooks/onboard"
ops_webhook_secret: str = ""

Montar em main.py: routers assist se necessário.

6.2 Secret partilhado

VM112 .env:

OPS_WEBHOOK_SECRET=<same-as-VM122-WEBHOOK_SECRET>
OPS_WEBHOOK_ENABLED=true

VM122 .env:

WEBHOOK_SECRET=<shared>

7. Plano de implementação (fases)

Fase 1 — Wizard backend (P1) — ~2-3 dias

Task Ficheiro Esforço
Criar admin_domain_validation.py services/ M
Integrar 4 checks em infrastructure.get_status() infrastructure.py S
Step admin_infra em provision() infrastructure.py M
Config settings config.py S
Testes unitários checks tests/ M

Fase 2 — Wizard frontend (P1) — ~1-2 dias

Task Ficheiro Esforço
UI steps admin no ProcessHub frontend/ M
Link admin pós-onboarding App.jsx S
Botão «Sincronizar admin» frontend/ S

Fase 3 — Webhooks VM112→VM122 (P1) — ~1-2 dias

Task Ficheiro Esforço
Settings ops_webhook config.py, .env S
Emit infra.synced extendido onboarding.py S
Emit admin.validation.failed onboarding.py S
Handlers VM122 api/app/ M

Fase 4 — Desk UI admin widget (P2) — ~2-3 dias

Task Ficheiro Esforço
Secção admin no ticket detail frontend-desk/ M
Widget dashboard domínios frontend-desk/ M
Endpoint proxy admin-status api/app/ S
Runbook ERR_CERT na UI docs/ S

Fase 5 — Automação ops (P2) — ~1 dia

Task Esforço
Cron sync Traefik certs semanal S
Alert cert expiring → VM122 M
Documentar zmproxyconfgen-ligbox em runbook Desk S

Total estimado: 7-11 dias dev.


8. Critérios de aceitação integração

Wizard

  • GET infrastructure/status/{domain} inclui 4 steps admin
  • POST infrastructure/provision executa admin_infra automaticamente
  • UI mostra estado admin no ProcessHub
  • Link mail.{dominio}/admin no passo Concluído
  • Novo domínio onboarding → admin_ready=true sem intervenção manual

VM122 Desk

  • infra.synced aparece na timeline do ticket
  • admin.validation.failed cria ticket com runbook
  • Widget «Admin domínio» no detalhe do ticket
  • Dashboard lista domínios com status admin
  • Técnico consegue re-validar via API sem SSH

Ops

  • Cron sync certs Traefik documentado e activo
  • Runbook Desk para ERR_CERT / 504 / redirect
  • zmproxyconfgen-ligbox referenciado em procedimento padrão

9. Referências

Documento Conteúdo
SPEC-CORRECAO-ADMIN-DOMINIOS-VIRTUAIS.md Correcção implementada VM112
SPEC-ADMIN-DOMINIO-BLINDAGEM-NGINX.md Blindagem nginx
SPEC-CARBONIO-ADMIN-LOGIN-FLOW-VALIDATION.md Fluxo E1E8
ligbox-ops-platform/specs/001-webhook-vm112-integration/ Webhook MVP
ligbox-ops-platform/specs/004-onboard-funnel-events/ Funil onboarding
ligbox-ops-platform/specs/009-ops-audit-overview/ Audit scorecard

10. Sincronização documentação

Destino Caminho
VM112 /opt/ligbox-deploy/docs/SPEC-INTEGRACAO-ADMIN-WIZARD-VM122-DESK.md
Obsidian /root/obsidian-infra/carbonio/carbonio-server/docs/
VM122 /root/obsidian-infra/ligbox-ops-platform/specs/010-admin-domain-validation/
GitHub itecnologys/ibytera-mail-portal + ligbox-ops-platform

Roger — planeamento integração Wizard + Desk — 2026-06-12