# 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 |
