ligbox-ops-platform/specs/043-desk-client-activation-sync/contracts/webmail-release-gate.md
Ligbox Spec Hub 3cb51e7ba7 spec 043/044: webmail gate contrato, chat bruto e sync Obsidian
Documenta liberação formal webmail (company_gate), decisões UX Painel Admin,
links Spec 044 tickets FOSS↔Desk, VM112 e chat bruto da sessão Roger.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-01 19:35:33 +00:00

148 lines
5.1 KiB
Markdown

# Contrato — Liberação formal webmail (`company_gate`)
**Spec:** [043](../spec.md) · [023](../../023-billing-recurrence-desk-visibility/spec.md) · [035 domain-manager](../../035-ligbox-mail-bundles-foss-openpanel/domain-manager-console-ui.md)
**VM:** 112 (`company_gate.py`, `DomainAdmin.jsx`)
**Versão:** 1.0 · 2026-07-01 · Roger
**Status:** Backend ✅ · UI Painel Admin ⏳ pendente
**Chat bruto:** [CHAT_BRUTO_WEBMAIL_GATE_TICKETS_SPEC043_044_20260701.txt](../../../chat-bruto/CHAT_BRUTO_WEBMAIL_GATE_TICKETS_SPEC043_044_20260701.txt)
---
## 1. Duas camadas de «activar webmail»
| Camada | O quê | Quem | Flag / API |
|--------|-------|------|------------|
| **A — Infra** | Traefik, cert LE, SNI, HTTPS `mail.{dom}` | Sistema automático | `infrastructure.ready` |
| **B — Gate formal** | Gerente confirma empresa + libera webmail (2FA Ligbox) | Gerente domínio | `webmail_released_at` |
**Regra:** camada A não remove aviso da camada B. Login Carbonio pode funcionar antes da liberação formal — aviso é informativo.
---
## 2. Onde fica cada mensagem (decisão Roger 2026-07-01)
| Superfície | Mensagem | Tipo |
|------------|----------|------|
| **Login Carbonio** `mail.{dom}` | Rodapé: *«Aviso: ambiente operacional — aguarda activação formal pelo Gerente do Domínio no Painel Ligbox…»* | Informativo (não bloqueia) |
| **Wizard** passo Concluído | *«Conta criada — webmail em activação»* (infra pendente) | Técnico |
| **Wizard** `WebmailReleaseModal` | Confirmar empresa + liberar com 2FA | Acção gerente (onboarding) |
| **Painel Admin** `/admin` **Início** | Banner P0 + card «Activar webmail» | Acção gerente (**UI falta**) |
| **Painel Admin** Contas / Resumo | Badge `WEBMAIL ⏳` / `WEBMAIL ✓` | Estado secundário |
| **Sidebar** «Abrir Webmail» | Desactivado até `webmail_released_at` | Evita 502/confusão |
**Não colocar** a acção de liberar só no rodapé do Carbonio — utilizador final vê aviso; **gerente actua no Painel Ligbox**.
---
## 3. Fluxo backend (VM112)
```
Onboarding concluído
→ domain_registry (sem webmail_released_at)
→ sync_webmail_user_notice() → Carbonio login footer
Gerente confirma empresa
→ POST /api/domain-admin/gate/company-profile
→ company_profile_confirmed_at
→ webhook company.validated → Desk (Spec 043)
Gerente libera webmail (2FA Ligbox)
→ POST /api/domain-admin/gate/release-webmail
→ webmail_released_at
→ sync_webmail_user_notice() limpa aviso
→ webhook webmail.released → Desk
```
### Ficheiros VM112
| Ficheiro | Função |
|----------|--------|
| `backend/app/services/company_gate.py` | Gate, mensagens, webhooks |
| `backend/app/routers/domain_admin.py` | `/gate/status`, `/gate/company-profile`, `/gate/release-webmail` |
| `backend/app/services/webmail_pending_page.py` | Página pública aguardando liberação |
| `frontend/src/components/WebmailReleaseModal.jsx` | Modal wizard (onboarding) |
| `frontend/src/DomainAdmin.jsx` | Painel gerente — **falta UI gate** |
### Constantes (`company_gate.py`)
```python
PENDING_WEBMAIL_USER_DESCRIPTION = (
"Aviso: ambiente operacional — aguarda activação formal pelo Gerente do Domínio "
"no Painel Ligbox. Utilização de correio permitida."
)
```
Injectado via `carbonio.set_domain_web_ui_notice()`.
---
## 4. API Painel Admin
### `GET /api/domain-admin/gate/status`
```json
{
"domain": "dratcoin.com",
"needs_company_confirm": false,
"webmail_released": false,
"service_active": false,
"webmail_url": "https://mail.dratcoin.com/",
"ops_ticket_state": "awaiting_billing_validation",
"pending_message": "Este webmail aguarda activação pelo Administrador do domínio..."
}
```
### `POST /api/domain-admin/gate/release-webmail`
```json
{
"ligbox_login": "roger",
"totp_code": "123456",
"recovery_code": null
}
```
**Pré-requisitos:** `company_profile_confirmed_at` preenchido; 2FA portal user válido.
---
## 5. Webhooks Desk
| Evento | Quando |
|--------|--------|
| `company.validated` | Após confirmar perfil empresa |
| `webmail.released` | Após `release_webmail()` |
Desk: `FUNNEL_STAGE` rank 8 = `webmail_released` (`main.py` VM122).
---
## 6. UI pendente — Painel Admin (`DomainAdmin.jsx`)
Wireframe **Início** (`/admin`):
```
┌─ Activar webmail ─────────────────────────────────────┐
│ Empresa: ⏳ confirmar | Webmail: ⏳ aguarda liberação │
│ [ Confirmar dados empresa ] [ Activar webmail + 2FA ] │
└─────────────────────────────────────────────────────────┘
```
Reutilizar lógica de `WebmailReleaseModal.jsx` + `me.gate` da API `/me`.
---
## 7. Caso dratcoin.com (Roger 2026-07-01)
- Login `mail.dratcoin.com` mostra aviso no rodapé ✅ (esperado)
- Erro *Credentials are not valid* = senha/email incorrectos (separado do gate)
- Painel `/admin` não mostra card liberar — **gap UI**
---
## Histórico
| Versão | Data | Notas |
|--------|------|-------|
| 1.0 | 2026-07-01 | Decisão UX mensagens + mapa company_gate |