---
id: MOD-INSTITUCIONAL-FALECONOSCO
tipo: modulo
onda: 4
status: concluido
unidades: [MOD-INSTITUCIONAL-FALECONOSCO]
fontes:
  - V2/Modules/Institucional/FaleConosco/
depende_de: [CORE-BOOT, CORE-AUTH, CORE-CMS, CORE-RUNTIME, SVC-MAILSERVICE, SVC-SEO, SVC-ACTIVITYLOGGER]
consumidores: [SVC-DASHBOARD, SVC-MAILSERVICE, UI-CMS, UI-PORTAL, MOD-SUPPORT-STRUCTURALLANDINGEDITOR]
criticidade: alta
dono: InstitucionalA
---

# Institucional/FaleConosco

> Formulário público de contato + caixa de entrada no CMS. O visitante envia nome, e-mail,
> telefone, assunto e mensagem; a linha é gravada em `v2_mensagens_contato` e, **se houver
> configuração**, dois e-mails saem pelo `MailService` (notificação interna e auto-resposta).
> O operador lê (marcando como lida), responde por e-mail e arquiva. O módulo não tem tela
> de configuração: os dados exibidos em `/fale-conosco` vêm do Editor Estrutural (SLE) e as
> chaves de comportamento (`contato_*`) não têm formulário.

## 0. Ficha de identidade

| Campo | Valor |
|---|---|
| Efeito primário | Persiste a mensagem do formulário público e mostra/permite responder/arquivar essas mensagens no CMS; os e-mails são tentados, mas **nunca** alteram a resposta ao usuário (o retorno é ignorado). |
| Entrada | `GET|POST /fale-conosco` (público) e `GET /cms/fale-conosco`, `GET /cms/fale-conosco/{id}`, `POST /cms/fale-conosco/{id}/reply`, `POST /cms/fale-conosco/{id}/archive`; campos `name`, `email`, `phone`, `subject`, `message`, `g-recaptcha-response`, `reply_body`. |
| Saída | HTML `v2-faleconosco::portal.index` e `v2-faleconosco::cms.{inbox,show}`; `302` com flash; linhas em `v2_mensagens_contato`; tentativas em `v2_mail_logs`; `activity_log`; JSON-LD `ContactPage`. |
| Efeitos colaterais | `is_read` ao abrir a mensagem; `replied_at`/`reply_body` ao responder; `is_archived` ao arquivar; e-mails (notificação/auto-resposta/resposta) com template cru (`use_template=false`); logs de erro de mail; sem limpeza de cache (a rota é excluída do cache). |
| Particularidade central | O chamador ignora o `MailResult` e o `MailService` **não lança em falha de transporte/envio** (só propaga erros anteriores ao `try` interno, como falha de banco ao ler a config SMTP); portanto `Resposta enviada com sucesso!`/`Mensagem enviada com sucesso! Entraremos em contato em breve.` aparecem mesmo quando nenhum e-mail saiu. |
| Como se integra | View namespace `v2-faleconosco`; model `MensagemContato`; `MailService::send`; `SEOService`; `LayoutBaseConfig` (SLE) para os dados de contato; `activity_log`; Dashboard lê contagens. |
| Se removido, quebra | `/fale-conosco` cai no `BasicPage` semeado (HTML estático com formulário `action="#"`), o CMS perde a caixa de entrada, o Dashboard perde o card de não lidas e nenhuma mensagem nova é gravada. |
| Superfície pública | `MensagemContato` (scopes, `markAsRead`), `FaleConoscoPortalController@{index,store}`, `FaleConoscoCmsController@{inbox,show,reply,archive}`. |

## 1. Efeito

### 1.1 O que o usuário consegue fazer

- **Visitante**: abrir `/fale-conosco`, ver dados de contato do SLE (telefone, e-mail,
  endereço, CEP, caixa postal, horário, mapa) e enviar uma mensagem
  (`Views/portal/index.blade.php:45-219`).
- **Visitante**: receber a confirmação `Mensagem enviada com sucesso! Entraremos em contato em breve.`
  e voltar ao formulário (`FaleConoscoPortalController.php:161-163`).
- **Operador CMS com `read`**: ver a caixa de entrada, buscar por nome/e-mail/assunto,
  filtrar “Apenas não lidas” e abrir a mensagem (`FaleConoscoCmsController.php:44-87`).
- **Operador com `write`**: responder por e-mail e arquivar (`:94-153`).
- **Operador**: ver no topo o total e o badge de não lidas (`inbox.blade.php:22-31`).

### 1.2 O que muda no sistema

| Efeito | Onde é produzido | Fonte |
|---|---|---|
| INSERT em `v2_mensagens_contato` com `id=v2_uuid()`, `ip_address`, `user_agent`, `is_read=false`, `is_archived=false` | `store` | `FaleConoscoPortalController.php:105-114`; migration `:21-41` |
| Tentativa de e-mail interno `[Contato] {subject}` para `contato_recipient_email` (se não vazio) | `store` | `:116-135` |
| Tentativa de auto-resposta para o visitante se `contato_auto_reply_body` não vazio | `store` | `:137-159` |
| `is_read=true` (só se estava `false`) ao abrir `/cms/fale-conosco/{id}` | `show`/`markAsRead` | `FaleConoscoCmsController.php:73-78`; `MensagemContato.php:71-79` |
| `activity_log` `read` ao abrir, mesmo que já lida | `show` | `:80-84` |
| `reply_body` + `replied_at=now()` antes da tentativa de envio | `reply` | `:103-105` |
| Tentativa de e-mail `Re: {subject}` para o visitante com o corpo cru | `reply` | `:107-117` |
| `activity_log` `replied` | `reply` | `:122-126` |
| `is_archived=true` | `archive` | `:137-142` |
| `activity_log` `archived` | `archive` | `:144-148` |
| `v2_mail_logs` (`sent`/`failed`, corpo incluído) para cada tentativa | `MailService::logMail` | `MailService.php:360-380` |
| `activity_log` **não** é gerado no envio público | — | `FaleConoscoPortalController.php:70-164` |

### 1.3 Contrato observável (entrada → saída)

| Entrada | Resultado |
|---|---|
| `GET /fale-conosco` | `200` com formulário + cartão de informações; dados do SLE; SEO fixo; JSON-LD `ContactPage`. |
| `POST /fale-conosco` válido | INSERT; tenta e-mails; `302` para `v2.fale-conosco.portal.index` + flash `Mensagem enviada com sucesso! Entraremos em contato em breve.` |
| `POST` sem `name`/`email`/`subject`/`message` | `302` de volta com erros de validação exibidos como **chaves cruas** (`validation.required`, `validation.email`), pois não existe `resources/lang` e o translator devolve a própria chave. |
| `POST` com `phone` fora do formato | `302` de volta com `validation.regex`; nada é gravado. |
| `POST` com `message` > 10000 | `302` com `validation.max.string`. |
| `POST` com `g-recaptcha-response` presente e inválido | `302` back com input + flash `Falha na verificação do reCAPTCHA. Tente novamente.`; nada é gravado. |
| `POST` sem o campo `g-recaptcha-response` | reCAPTCHA **não** é verificado (bypass por omissão do campo). |
| `POST` com `contato_recipient_email` vazio/ausente | nenhum e-mail interno; mensagem gravada e sucesso exibido. |
| `POST` com `contato_auto_reply_body` vazio/ausente | nenhuma auto-resposta; sucesso exibido. |
| `POST` com SMTP inválido | mensagem gravada; `v2_mail_logs` com `status='failed'`; sucesso exibido (o erro não chega ao visitante). |
| `GET /cms/fale-conosco` | `200` com `$mensagens` (20/página, desc) e `$unreadCount`. |
| `GET /cms/fale-conosco?unread=1` | **`500`** `BadMethodCallException: Method boolean does not exist.` (Laravel 5.5 não tem `Request::boolean`) (`FaleConoscoCmsController.php:58`). |
| `GET /cms/fale-conosco/{id}` | `200`; marca lida; `activity_log read`. |
| `GET /cms/fale-conosco/{id}` inexistente | `404`. |
| `POST /cms/fale-conosco/{id}/reply` sem corpo | `302` back com `validation.required`. |
| `POST .../reply` com corpo > 10000 | `302` back com `validation.max.string`. |
| `POST .../reply` válido | grava `reply_body`/`replied_at`, tenta enviar, `302` back + `Resposta enviada com sucesso!` (mesmo se o envio falhou). |
| `POST .../archive` | `is_archived=true`, `302` para a inbox + `Mensagem arquivada com sucesso!`; a mensagem some da lista. |
| Acesso CMS sem sessão/papel | `302` login; `401` em AJAX (`CmsAuthenticate.php:21-44`). |

### 1.4 O que este módulo NÃO faz

- Não tem tela de configuração de contato: o comentário da rota aponta para o SLE
  (`Routes/cms.php:13-15`).
- Não grava `contato_*` em lugar nenhum: são chaves somente-leitura para o módulo.
- Não tem caixa de saída, threads, anexos, encaminhamento, cópia ou template de e-mail.
- Não valida spam de forma efetiva: sem throttle, sem honeypot, sem captcha obrigatório.
- Não usa `created_by` (coluna existe, nunca é escrita).
- Não expõe mensagens arquivadas em nenhuma tela (sem filtro/aba).
- Não apaga mensagens fisicamente (só arquiva; soft delete não é usado no fluxo).
- Não notifica o remetente sobre o status (a resposta só existe se o operador responder).
- Não registra auditoria do envio público.
- Não limpa o cache de páginas (não é necessário; a rota está fora do cache).

## 2. Abordagem

### 2.1 Estratégia em uma página

Um CRUD de mensagens com dois atores: o público escreve (INSERT + tentativas de e-mail
best-effort) e o CMS lê/responde/arquiva. Toda a integração de e-mail é opcional e
silenciosa; a única configuração são três chaves em `v2_portal_configs` e os dados
exibidos, que vêm de outra tabela/editor (SLE).

```mermaid
flowchart LR
  V[Visitante] -->|POST /fale-conosco| V1[validate + recaptcha condicional]
  V1 --> DB[(v2_mensagens_contato)]
  DB --> M1[MailService: notificacao]
  DB --> M2[MailService: auto-resposta]
  M1 --> LOG[(v2_mail_logs)]
  M2 --> LOG
  O[Operador CMS] -->|GET inbox/show| QB[(mensagens inbox)]
  O -->|POST reply| DB
  DB --> M3[MailService: Re:]
  O -->|POST archive| DB
  O --> AL[(activity_log)]
```

### 2.2 Mecânica passo a passo

1. **Boot**: rotas CMS sob `web` + `module.active:FaleConosco` (provider) e
   `CmsAuthenticate` (arquivo); rotas web sob `web` + manutenção + `page.cache` +
   `public.cache`, mas ambos os middlewares de cache excluem `fale-conosco`
   (`V2ServiceProvider.php:215-219,299-306`; `PageCacheMiddleware.php:16-23`;
   `PublicCacheMiddleware.php:31-36`).
2. **GET portal**: define SEO fixo (title/description/keywords), lê
   `LayoutBaseConfig::where('key','contato')` e mapeia `payload[telefone_1|email|endereco|horario|map_link|zipcode|po_box]`,
   depois mescla todas as chaves do grupo `CONTATO` de `v2_portal_configs`
   (`FaleConoscoPortalController.php:34-64`).
3. **POST portal**: `validate` 5 campos; se existir `g-recaptcha-response`, chama
   `siteverify` via cURL síncrono com `secret` (config inexistente → `''`), `response` e
   `remoteip`; falha → flash de erro + back com input (`:72-103`).
4. Cria `MensagemContato`, preenche id/nome/e-mail/telefone/assunto/mensagem/IP/UA e salva
   (`:105-114`).
5. Lê `contato_recipient_email`; se não vazio, monta corpo HTML escapado e chama
   `MailService::send` em `try/catch` que, para falhas de SMTP, nunca captura (o serviço devolve `MailResult(false)`); falhas na leitura da config SMTP, por ocorrerem antes do `try` do serviço, ainda podem propagar
   (`:116-135`).
6. Lê `contato_auto_reply_subject` e `contato_auto_reply_body`; se o corpo não for vazio,
   envia a auto-resposta (`:137-159`).
7. Flash de sucesso e redirect à página (`:161-163`).
8. **Inbox**: `MensagemContato::inbox()` + busca opcional + filtro `unread` (bug) +
   contagem de não lidas + `recent()->paginate(20)` (`FaleConoscoCmsController.php:44-66`).
9. **Show**: `findOrFail`, `markAsRead`, `activity_log read`, view (`:73-87`).
10. **Reply**: valida `reply_body`, grava campos, tenta `MailService::send` com
    `Re: {subject}`, audita e faz `back()` (`:94-131`).
11. **Archive**: `is_archived=true`, audita, flash, redirect inbox (`:137-153`).

### 2.3 Decisões de design e por quê

- **E-mail como efeito best-effort**: a mensagem é o dado durável; e-mail é conveniência.
  A ausência de transação entre INSERT e envio é coerente com isso `[C]`.
- **Configuração por chave, não por tabela**: `v2_portal_configs` evita schema novo; o custo
  é não haver UI nem defaults `[C]` (`:116-142`).
- **Dados de exibição no SLE**: contato é dado institucional compartilhado com header/footer;
  duplicar aqui criaria duas fontes `[C]` (`:40-53`; comentário em `Routes/cms.php:13-15`).
- **Captcha opcional**: só valida se o campo existir, permitindo que a página sem widget
  funcione; na prática é um no-op `[C]` (`:80-103`).
- **Arquivar em vez de deletar**: preserva histórico; sem UI de restauração `[C]`
  (`:137-142`).
- **Resposta inline (`reply_body` único)**: uma mensagem = no máximo uma resposta; o form
  desaparece depois (`show.blade.php:92-116`), mas o endpoint continua aceitando novas
  respostas e sobrescrevendo `reply_body`/`replied_at`.

### 2.4 Trechos de código pivô

```php
// V2/Modules/Institucional/FaleConosco/Controllers/FaleConoscoPortalController.php:72-78 — validação pública
$this->validate($request, [
    'name'    => 'required|string|max:255',
    'email'   => 'required|email|max:255',
    'phone'   => 'nullable|string|max:16|regex:/^\([0-9]{2}\)\s[0-9]{4,5}-[0-9]{4}$/',
    'subject' => 'required|string|max:255',
    'message' => 'required|string|max:10000',
]);
```

O telefone só aceita `(DD) 9999-9999` ou `(DD) 99999-9999` com **um espaço** após o DDD e
hífen antes dos 4 últimos dígitos; é opcional. A validação é inline (sem FormRequest).

```php
// V2/Modules/Institucional/FaleConosco/Controllers/FaleConoscoPortalController.php:80-102 — reCAPTCHA condicional
if ($request->has('g-recaptcha-response')) {
    $recaptchaResponse = $request->input('g-recaptcha-response');
    $secret = config('v2.recaptcha.secret', '');
    $verifyUrl = 'https://www.google.com/recaptcha/api/siteverify';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $verifyUrl);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
        'secret'   => $secret,
        'response' => $recaptchaResponse,
        'remoteip' => $request->ip(),
    ]));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    curl_close($ch);

    $result = json_decode($response, true);
    if (!$result || !isset($result['success']) || !$result['success']) {
        flash('Falha na verificação do reCAPTCHA. Tente novamente.')->error();
        return redirect()->back()->withInput();
    }
}
```

Não há `v2.recaptcha.secret` em `config/v2.php` (94 linhas, sem a chave), portanto o
`secret` enviado é `''`; se um cliente enviar o campo, o Google responde `success:false` e o
envio é bloqueado. Como a view do módulo não renderiza o widget, o caminho normal é o
bypass pelo campo ausente.

```php
// V2/Modules/Institucional/FaleConosco/Controllers/FaleConoscoPortalController.php:116-135 — notificação interna
$recipientEmail = DB::table('v2_portal_configs')
    ->where('config_key', 'contato_recipient_email')->value('config_value');

if (!empty($recipientEmail)) {
    try {
        $body = 'Nome: ' . $mensagem->name . '<br>' .
                'Email: ' . $mensagem->email . '<br>' .
                'Telefone: ' . ($mensagem->phone ?: '-') . '<br><br>' .
                'Mensagem:<br>' . nl2br(e($mensagem->message));

        $this->mailService->send($recipientEmail, '[Contato] ' . $mensagem->subject, $body, [
            'to_name' => 'Administrador', 'use_template' => false, 'is_html' => true,
        ]);
    } catch (\Exception $e) {
        \Log::error('[FaleConosco] Falha ao enviar notificação admin: ' . $e->getMessage());
    }
}
```

Assunto e corpo são literais; `name`/`email`/`phone` não são escapados no corpo (apenas a
mensagem). O retorno de `send()` é descartado. O `catch` só atua em falhas anteriores ao `try` do serviço (ex.: banco indisponível na leitura da config SMTP); falha de envio é convertida em `MailResult(false)` (próximo trecho).

```php
// V2/Services/MailService/MailService.php:126-133 — falha de envio vira MailResult false
} catch (\Exception $e) {
    $errorMsg = $e->getMessage();
    Log::error('[MailService] Erro ao enviar e-mail para ' . $to . ': ' . $errorMsg);

    // Log de falha
    $this->logMail($profile, isset($config) ? $config->from_address : null, $to, $subject, $body, 'failed', null, $errorMsg);

    return $this->buildResult(false, 'Erro ao enviar e-mail.', null, $errorMsg);
}
```

O serviço captura a exceção e devolve `MailResult(false, 'Erro ao enviar e-mail.')`; os
`try/catch` dos chamadores não disparam para falhas de envio (apenas para falhas pré-`try`, como erro de banco). `logMail` grava a tentativa em `v2_mail_logs`
(inclusive o corpo) e também engole exceções (`MailService.php:360-380`).

```php
// V2/Modules/Institucional/FaleConosco/Controllers/FaleConoscoCmsController.php:94-130 — resposta do operador
$mensagem = MensagemContato::findOrFail($id);
$this->validate($request, ['reply_body' => 'required|string|max:10000']);

$mensagem->reply_body = $request->input('reply_body');
$mensagem->replied_at = now();
$mensagem->save();

try {
    $this->mailService->send($mensagem->email, 'Re: ' . $mensagem->subject,
        $request->input('reply_body'), [
            'to_name' => $mensagem->name, 'use_template' => false, 'is_html' => true,
        ]);
} catch (\Exception $e) {
    \Log::error('[FaleConosco] Falha ao enviar email de resposta: ' . $e->getMessage());
}

$this->activityLogger->log($mensagem, 'replied', [...]);
flash('Resposta enviada com sucesso!')->success();
return redirect()->back();
```

A ordem importa: `reply_body`/`replied_at` são persistidos **antes** do envio; se o envio
falhar, a UI continua mostrando a resposta como enviada e o formulário de resposta
desaparece (`show.blade.php:77-116`). O corpo é enviado sem escape (`is_html=true`), então
o operador pode inserir HTML.

```php
// V2/Modules/Institucional/FaleConosco/Controllers/FaleConoscoCmsController.php:44-64 — inbox e o filtro quebrado
$query = MensagemContato::inbox();
if ($request->has('search') && !empty($request->input('search'))) { /* name|email|subject ilike */ }
if ($request->has('unread') && $request->boolean('unread')) {
    $query->unread();
}
$unreadCount = MensagemContato::inbox()->unread()->count();
$mensagens = $query->recent()->paginate(20);
```

`Request::boolean()` não existe no Laravel 5.5 (o framework é `5.5.*` no `composer.json`);
o `Request` usa `Macroable`, então a chamada lança `BadMethodCallException` — a inbox
quebra sempre que a query `unread` é enviada, embora o checkbox exista na tela
(`inbox.blade.php:39-45`).

```blade
{{-- V2/Modules/Institucional/FaleConosco/Views/portal/index.blade.php:57-120 — formulário --}}
<form action="{{ route('v2.fale-conosco.portal.store') }}" method="POST">
    {{ csrf_field() }}
    ...
    <input type="text" id="name" name="name" class="form-control" required
           value="{{ old('name') }}" placeholder="Seu nome completo" maxlength="255">
    ...
    <input type="tel" id="phone" name="phone" class="form-control"
           value="{{ old('phone') }}" placeholder="(61) 99999-9999"
           data-mask="phone" maxlength="16" inputmode="tel">
    ...
    <textarea id="message" name="message" class="form-control" rows="6" required
              placeholder="Digite sua mensagem...">{{ old('message') }}</textarea>
    <div class="form-text">Máximo de 10.000 caracteres.</div>
```

Não há `g-recaptcha` nem script do Google na view do módulo; o `data-mask="phone"` aplica a
máscara de `public/assets/js/masks.js:39-60`, compatível com a regex do servidor.

### 2.5 Algoritmos, consultas e custos

- **GET portal**: 1 select em `v2_layout_base_configs` (por `key='contato'`) + 1 select
  `pluck` em `v2_portal_configs` do grupo `CONTATO`; sem cache.
- **POST portal**: validação → (cURL síncrono opcional ao Google) → 1 INSERT → até 2 selects
  de config + até 2 envios SMTP + 2 inserts em `v2_mail_logs`. Latência dominada pelo SMTP;
  não há fila/assíncrono.
- **Inbox**: 1 count de não lidas + 1 select paginado; busca `ILIKE` sem índice.
- **Show**: 1 select + eventual UPDATE (`is_read`) + 1 insert em `activity_log`.
- **Reply/Archive**: 1 select + 1 UPDATE + (reply) SMTP + insert de log + insert de activity.
- `/fale-conosco` (GET) está fora do cache de página e do cache HTTP (sem `X-Cache-Status`).

## 3. Particularidades

### 3.1 O que só existe aqui

- **Configuração dividida entre SLE (exibição) e `v2_portal_configs` (comportamento)** sem
  tela para a segunda parte.
- **Captcha opcional por presença do campo**, com segredo inexistente na config.
- **Resposta com `use_template=false`**: os e-mails são HTML cru, sem o template visual do
  `MailService` (que é o default `true`).
- **“Sucesso” desacoplado do envio**: o único módulo institucional que promete retorno por
  e-mail sem verificar o resultado.

### 3.2 Invariantes e regras não óbvias

| ID | Regra | Efeito | Fonte |
|---|---|---|---|
| `RN-FALECONOSCO-01` | A mensagem é gravada antes de qualquer e-mail; não há transação entre eles. | Falha de SMTP não desfaz a mensagem. | `FaleConoscoPortalController.php:105-135` |
| `RN-FALECONOSCO-02` | `contato_recipient_email` vazio/ausente ⇒ nenhuma notificação; não há default. | Sem a chave, o operador só vê a mensagem na inbox. | `:116-120` |
| `RN-FALECONOSCO-03` | `contato_auto_reply_body` vazio/ausente ⇒ nenhuma auto-resposta; assunto default `Recebemos sua mensagem`. | Sem a chave, o visitante não recebe nada. | `:137-155` |
| `RN-FALECONOSCO-04` | `MailService::send` devolve `MailResult` e não lança em falha de transporte/envio; exceções antes do `try` (config SMTP no banco) ainda propagam. | UI sempre mostra sucesso em falha de envio; o `try/catch` do chamador só cobre falhas pré-`try`. | `MailService.php:126-133`; `FaleConoscoPortalController.php:131-134,156-158` |
| `RN-FALECONOSCO-05` | `show` marca `is_read=true` (só se necessário) e audita **toda** abertura. | Abrir repetidamente gera múltiplos `read`; a contagem de não lidas cai só na primeira. | `FaleConoscoCmsController.php:78-84`; `MensagemContato.php:71-79` |
| `RN-FALECONOSCO-06` | `reply` grava `reply_body`/`replied_at` antes do envio e não verifica o resultado. | Resposta “enviada” mesmo com falha; reenvio sobrescreve a anterior. | `:103-128` |
| `RN-FALECONOSCO-07` | `is_archived=true` remove da inbox (scope `inbox`) e não há tela para reverter. | Mensagem arquivada fica inacessível pela UI. | `MensagemContato.php:96-108`; `FaleConoscoCmsController.php:137-152` |
| `RN-FALECONOSCO-08` | A validação de telefone exige `(DD) 9999-9999` ou `(DD) 99999-9999`, máximo 16. | Formatos livres são rejeitados. | `FaleConoscoPortalController.php:75` |
| `RN-FALECONOSCO-09` | O reCAPTCHA só roda quando `g-recaptcha-response` está presente; o segredo é `config('v2.recaptcha.secret','')` (chave inexistente). | Sem widget não há verificação; com campo e segredo vazio, bloqueia. | `:80-103`; `config/v2.php:1-94` |
| `RN-FALECONOSCO-10` | `unread` usa `Request::boolean()`, inexistente no Laravel 5.5. | `GET /cms/fale-conosco?unread=1` → 500. | `FaleConoscoCmsController.php:58`; `composer.json:15` |
| `RN-FALECONOSCO-11` | A inbox ordena por `created_at DESC` e pagina 20; busca cobre `name`, `email`, `subject` (não a mensagem). | Mensagem não é pesquisável. | `:49-64`; `MensagemContato.php:114-117` |
| `RN-FALECONOSCO-12` | O módulo não tem permissão de rota própria: RBAC pelo módulo `FaleConosco` via `active_pattern`. | `read` vê/abre; `write` responde/arquiva. | `ModuleProvider.php:23`; `V2PermissionMiddleware.php:40-101` |
| `RN-FALECONOSCO-13` | Rotas GET e POST são excluídas de `page.cache` (`fale-conosco*`) e de `public.cache` (`/fale-conosco`). | Nenhum `Cache-Control` público nem HTML cacheado. | `PageCacheMiddleware.php:16-23`; `PublicCacheMiddleware.php:31-36,70-76` |
| `RN-FALECONOSCO-14` | `metadata` está no `$fillable`/casts do model, mas **não** existe na tabela. | Qualquer uso futuro de `metadata` gera erro de coluna inexistente. | `MensagemContato.php:22-44`; migration `:21-41` |
| `RN-FALECONOSCO-15` | `created_by` existe na tabela e não no `$fillable`; nunca é escrito. | Coluna sempre `NULL`. | migration `:34`; model `:22-36` |

### 3.3 Casos-limite e comportamentos surpreendentes

- **Sem `contato_*` no banco** (o caso do seed atual): a mensagem é gravada, mas nenhum
  e-mail é tentado; o visitante vê “Entraremos em contato em breve.” sem que ninguém seja
  notificado.
- **Chave com `''`**: `!empty('')` é falso → trata como ausente.
- **`contato_auto_reply_subject` vazio com body preenchido** → assunto `Recebemos sua mensagem`.
- **Falha de SMTP** → `v2_mail_logs.status='failed'`, `error_message` com a exceção, corpo
  armazenado; a UI não mostra nada.
- **Sem coluna `metadata`** → o cast nunca é exercitado; `MensagemContato::create([...])` com
  `metadata` falharia.
- **Abrir mensagem já arquivada** pela URL direta → funciona (findOrFail não filtra
  `is_archived`), marca lida e audita.
- **Responder mensagem arquivada** → funciona pela URL; volta para a página anterior.
- **Duas respostas** → a segunda sobrescreve `reply_body` e `replied_at`; o histórico da
  primeira se perde.
- **Filtro `unread`** → 500 antes de renderizar; o checkbox “Apenas não lidas” é, na
  prática, um botão de erro.
- **IP/UA** → gravados crus; o IP vem de `$request->ip()` (pode ser o proxy se não houver
  `TrustProxies`).
- **CSRF** → o POST público exige token (`web`); um POST externo sem token recebe `419`.
- **Cache** → por estar excluída, a página sempre reflete o SLE atual (sem stale).
- **Rota pública vs BasicPage semeada**: a rota do módulo é registrada antes do fallback
  `/{slug}`; `/fale-conosco` usa o controller, e a linha `v2_basic_pages` criada pelo seeder
  fica inacessível por essa URL (conteúdo legado/duplicado).

### 3.4 Armadilhas de reimplementação

- **Assumir que o e-mail é garantido**: a mensagem é o registro; e-mail é tentativa. Se o
  novo sistema prometer envio, o contrato muda (e o flash precisa mudar).
- **Remover o `try/catch`** achando que é redundante: ele cobre falhas pré-`try` do serviço (ex.: banco); falhas de envio são silenciosas por contrato.
- **Reaproveitar o `contato_*` como config de exibição**: os dados exibidos vêm do SLE;
  sobrescrever as chaves não muda o cartão.
- **Trocar `use_template=false` por `true`**: adiciona o template visual do MailService e
  altera o HTML recebido.
- **Implementar “não lidas” com `boolean()` em Laravel 5.5**: reproduz o 500; use
  `$request->input('unread')`/`filter`.
- **Adicionar paginação/abas sem tratar `is_archived`**: mensagens arquivadas não têm rota
  de volta; qualquer tela nova precisa definir isso.

### 3.5 Divergências documentação × código e dívidas

- **Comentário na rota CMS** afirma que as configurações foram movidas para o SLE; o
  controller ainda lê `contato_*` de `v2_portal_configs` e não há tela para elas
  (`Routes/cms.php:13-15`; `FaleConoscoPortalController.php:55-59`).
- **`ContatoConfig` marcado `@deprecated`** e sua tabela `v2_contato_configs` não tem
  escritor/leitor (`Models/ContatoConfig.php:7-11`).
- **`ModuleProvider` define `description` duas vezes**: a segunda (linha 34) vence, então a
  descrição exibida é a longa, não “Gerenciamento de mensagens e configurações de contato.”
  (`ModuleProvider.php:19-34`).
- **`metadata` no model sem coluna** (dívida de schema).
- **Sem `resources/lang`**: erros de validação são exibidos como chaves cruas
  (`validation.required`, `validation.email`, `validation.regex`, `validation.max.string`)
  (`config/app.php:84,97`).
- **Docs de SEO** classificam FaleConosco como “setters; baixo risco” — correto, mas o
  formulário não usa `seo-input` e não há SEO por página além dos setters
  (`03_servicos-ui/seo/contrato.md:429`).
- **O `BasicPage` semeado** duplica a página com HTML antigo e um formulário `action="#"`,
  inalcançável pela URL (ver §12).

## 4. Integrabilidade

### 4.1 Superfície pública

| Símbolo | Tipo | Assinatura | Precondição | Consumidores |
|---|---|---|---|---|
| `MensagemContato` | model | `$table='v2_mensagens_contato'`, UUID, soft delete | tabela migrada | controllers, Dashboard |
| `MensagemContato::scopeUnread` | scope | `unread()` | — | inbox/Dashboard |
| `MensagemContato::scopeInbox` | scope | `inbox()` → `is_archived=false` | — | inbox/Dashboard |
| `MensagemContato::scopeArchived` | scope | `archived()` | — | sem consumidor |
| `MensagemContato::scopeRecent` | scope | `recent()` → `created_at desc` | — | inbox |
| `MensagemContato::markAsRead` | método | `(): $this` | instância persistida | `show` |
| `MailService::send` | serviço | `send($to,$subject,$body,array $options): MailResult` | config SMTP ou fallback | portal/reply |
| `LayoutBaseConfig::where('key','contato')` | model externo | `payload` array | SLE instalado | portal |

### 4.2 Contrato de UI/JS

- **Portal**: form POST com `csrf_field()`; campos `name`, `email`, `phone` (máscara),
  `subject`, `message`; `old()` em todos para repopular após erro; `data-mask="phone"`.
- **Info**: cartão condicional por chave `$configs['phone'|'email'|'address'|'zipcode'|'po_box'|'business_hours'|'map_embed_url']`;
  mapa em iframe `ratio-16x9` com `loading="lazy"` e `title="Mapa de localização"`
  (`portal/index.blade.php:134-215`).
- **CMS inbox**: `table[aria-label="Mensagens"]`, linhas em negrito quando não lidas, badge
  de status, badge de não lidas no topo, `filter-card` com slot do checkbox
  (`inbox.blade.php:22-122`).
- **CMS show**: cartão com assunto/data/nome/e-mail/telefone/IP, mensagem em
  `nl2br(e(...))`, bloco de resposta anterior e form de resposta (`show.blade.php:18-116`).
- **Sem JS de módulo** no CMS (apenas `confirm()` inline no arquivar); sem AJAX.
- **CSRF**: forms usam `csrf_field()`; não há meta token manual.

### 4.3 Ordem e ciclo de vida

1. Provider registra rotas CMS e web; o grupo web é excluído dos dois caches.
2. A página pública depende de `LayoutBaseConfig` (SLE); se a tabela/classe não existir, a
   consulta lança erro (não há `try/catch`).
3. O envio depende de `MailService` resolvível; a config SMTP é lida do banco com fallback
   para `config/mail.php`.
4. `SEOService` é preenchido antes da view; o composer de metadata lê no `<head>`.
5. A inbox não depende de flags para renderizar, mas o Dashboard esconde o card quando o
   módulo está inativo.

### 4.4 Receitas de uso

```php
// Enviar uma mensagem equivalente ao formulário público (sem HTTP)
$m = new \V2\Modules\Institucional\FaleConosco\Models\MensagemContato();
$m->name = 'Fulano'; $m->email = 'fulano@exemplo.org'; $m->phone = null;
$m->subject = 'Dúvida'; $m->message = 'Texto';
$m->ip_address = request()->ip(); $m->user_agent = request()->userAgent();
$m->save(); // id gerado no boot do model se ausente
```

```php
// Consultar não lidas da inbox (mesma semântica da tela)
$count = \V2\Modules\Institucional\FaleConosco\Models\MensagemContato::inbox()->unread()->count();
```

```php
// Responder programaticamente (send() não lança em falha de transporte; verifique o resultado)
$result = app(\V2\Services\MailService\MailService::class)
    ->send($mensagem->email, 'Re: ' . $mensagem->subject, 'Corpo', [
        'to_name' => $mensagem->name, 'use_template' => false, 'is_html' => true,
    ]);
if (!$result->wasSuccessful()) { /* tratar */ }
```

### 4.5 Anti-uso

- **Confiar no flash de sucesso como prova de envio**: ele não depende do `MailResult`.
- **Usar `metadata` no `MensagemContato`**: a coluna não existe.
- **Filtrar mensagens por `created_by`**: sempre `NULL`.
- **Contar “não lidas” sem `inbox()`**: mensagens arquivadas continuariam contando se o
  escopo não fosse aplicado.

### 4.6 Custos e limites da integração

- Envio SMTP síncrono no request público (sem fila): latência e timeout do provedor afetam
  o tempo de resposta.
- Sem throttle/rate limit: qualquer cliente pode criar N mensagens e disparar N e-mails.
- `message`/`reply_body` até 10.000; `name`/`email`/`subject` 255; `phone` 16.
- Inbox 20/página; busca full scan em três colunas.
- `v2_mail_logs` cresce com cada tentativa e guarda o corpo (dados pessoais).

## 5. Rotas e contratos HTTP

| Tipo | Método | URI | Nome | Middleware | Controller@ação | Permissão | Efeito |
|---|---|---|---|---|---|---|---|
| grupo | — | `cms/fale-conosco` | — | `web`; `module.active:FaleConosco`; `CmsAuthenticate` | — | módulo `FaleConosco` | agrupa 4 endpoints |
| endpoint | GET | `/cms/fale-conosco` | `v2.fale-conosco.cms.inbox` | idem | `FaleConoscoCmsController@inbox` | `read` | lista inbox |
| endpoint | GET | `/cms/fale-conosco/{id}` | `v2.fale-conosco.cms.show` | idem | `@show` | `read` | detalhe + marca lida |
| endpoint | POST | `/cms/fale-conosco/{id}/reply` | `v2.fale-conosco.cms.reply` | idem | `@reply` | `write` | grava resposta + e-mail |
| endpoint | POST | `/cms/fale-conosco/{id}/archive` | `v2.fale-conosco.cms.archive` | idem | `@archive` | `write` | arquiva |
| grupo | — | — | — | `web`; `MaintenanceMiddleware`; `page.cache`; `public.cache` | — | pública | grupos excluídos dos caches |
| endpoint | GET | `/fale-conosco` | `v2.fale-conosco.portal.index` | idem | `FaleConoscoPortalController@index` | pública | formulário + infos |
| endpoint | POST | `/fale-conosco` | `v2.fale-conosco.portal.store` | idem | `@store` | pública | grava + tenta e-mails |

Detalhes completos em [`rotas.md`](rotas.md). Sem throttle, sem API, sem `FormRequest`.

## 6. Dados e modelo de domínio

### 6.1 `v2_mensagens_contato`

| Coluna | Tipo | Null | Default | Observação |
|---|---|---|---|---|
| `id` | `uuid` PK | não | — | `v2_uuid()` no boot do model ou no controller |
| `name` | `varchar(255)` | não | — | — |
| `email` | `varchar(255)` | não | — | validado como e-mail |
| `phone` | `varchar(50)` | sim | — | validação aceita só formato mascarado |
| `subject` | `varchar(255)` | não | — | — |
| `message` | `text` | não | — | até 10.000 na aplicação |
| `is_read` | `boolean` | não | `false` | cast boolean |
| `is_archived` | `boolean` | não | `false` | cast boolean |
| `replied_at` | `timestamp` | sim | — | cast datetime |
| `reply_body` | `text` | sim | — | sem limite de coluna; limite 10.000 na validação |
| `ip_address` | `varchar(45)` | sim | — | IPv4/IPv6 |
| `user_agent` | `text` | sim | — | cru |
| `created_by` | `varchar(36)` | sim | — | nunca escrito |
| `created_at`/`updated_at` | `timestamp` | sim | — | — |
| `deleted_at` | `timestamp` | sim | — | soft delete existe no model, mas o fluxo nunca apaga |

Índices: `idx_v2_msg_contato_read`, `idx_v2_msg_contato_archived`,
`idx_v2_msg_contato_created`. Sem FK/unique. Model com `$casts` (`is_read`, `is_archived`,
`replied_at`, `metadata`) e `$dates` (`created_at`, `updated_at`, `deleted_at`, `replied_at`).

### 6.2 `v2_contato_configs` (órfã/deprecated)

`id` uuid PK, `key` varchar(255) **unique**, `value` text null, timestamps, índice
`idx_v2_contato_configs_key`. Model `ContatoConfig` (deprecated) preenche `id` no `creating`,
`$casts=['metadata'=>'array']` e `$fillable` inclui `metadata` — coluna inexistente. Não há
nenhum uso em código (verificado por busca).

### 6.3 Tabelas externas lidas

- `v2_layout_base_configs` (`key='contato'`, `payload` JSON com `endereco`, `map_link`,
  `telefone_1`, `telefone_2`, `email`, `horario`, `zipcode`, `po_box`) — escrita pelo SLE
  (`LayoutBaseCmsController.php:185-199`).
- `v2_portal_configs` (`contato_recipient_email`, `contato_auto_reply_subject`,
  `contato_auto_reply_body`) — sem escritor no corpus.
- `v2_mail_logs` (log de tentativas).
- `activity_log`.

### 6.4 Escrita por coluna

`id/name/email/phone/subject/message/ip_address/user_agent`: `store`. `is_read`: `show`.
`reply_body/replied_at`: `reply`. `is_archived`: `archive`. `created_by/metadata/deleted_at`:
nunca.

## 7. Fluxos e estados

```mermaid
stateDiagram-v2
  [*] --> Nova: POST /fale-conosco
  Nova --> Lida: GET /cms/fale-conosco/{id}
  Lida --> Respondida: POST .../reply
  Nova --> Arquivada: POST .../archive
  Lida --> Arquivada: POST .../archive
  Respondida --> Arquivada: POST .../archive
  Arquivada --> Lida: GET direto pela URL (sem UI)
```

```mermaid
sequenceDiagram
  participant V as Visitante
  participant P as FaleConoscoPortalController
  participant DB as v2_mensagens_contato
  participant M as MailService
  participant L as v2_mail_logs
  V->>P: POST /fale-conosco
  P->>P: validate + recaptcha opcional
  P->>DB: INSERT
  P->>M: send(admin) [se config]
  M->>L: insert sent|failed
  P->>M: send(auto-resposta) [se body]
  M->>L: insert sent|failed
  P-->>V: 302 + flash de sucesso
```

## 8. UI CMS

Resumo (detalhe em [`cms.md`](cms.md)): inbox com total/badge, busca, checkbox de não lidas
(quebrado), tabela com status/nome/e-mail/assunto/data/ações e paginação; detalhe com dados
do remetente, mensagem escapada, resposta anterior e form de resposta condicional; ação de
arquivar em ambas as telas.

## 9. UI Portal

Resumo (detalhe em [`portal.md`](portal.md)): hero, formulário em card, cartão de
informações do SLE, mapa opcional, `ContactPage` JSON-LD, SEO fixo por setters, sem captcha
renderizado, sem cache.

## 10. Configuração, permissões e flags

**`ModuleProvider::getConfig()`** (`ModuleProvider.php:16-36`): título `Fale Conosco`,
ícone `bi bi-envelope`, posição `7`, `active_pattern=['cms/fale-conosco*']`, rota
`v2.fale-conosco.cms.inbox`, um submenu “Caixa de Entrada”; `description` declarada duas
vezes (a última vence).

**Permissões**: `permissions_v2['FaleConosco'] ∈ {none,read,write}` via
`V2PermissionMiddleware`; `CmsAuthenticate` exige papel; suporte/`super-admin` passam.

**Flags**: sem linha semeada em `v2_module_flags`; ausência ⇒ ativo. O Dashboard consulta
`ModuleFlagService::isActive('FaleConosco')`.

**Chaves de comportamento**: `contato_recipient_email`, `contato_auto_reply_subject`,
`contato_auto_reply_body` (sem default, sem tela). **Chave inexistente**:
`v2.recaptcha.secret` (default `''`).

## 11. Observabilidade, erros e limites

- **activity_log**: `read`, `replied`, `archived` (com `subject` e `from`/`to`). Sem registro
  no envio público.
- **Logs**: `[MailService] Erro ao enviar e-mail para {to}: {erro}` (error),
  `[MailService] Erro ao salvar log de e-mail: …`, `[FaleConosco] Falha ao enviar
  notificação admin: …`, `[FaleConosco] Falha ao enviar auto-resposta: …`,
  `[FaleConosco] Falha ao enviar email de resposta: …` (os três últimos são inalcançáveis
  no fluxo normal).
- **v2_mail_logs**: `profile`, `from_address`, `to_address`, `subject`, `body`, `status`
  (`sent|failed`), `message_id`, `error_message`, `sent_at`.
- **HTTP**: `302` (sucesso/validação/login/permissão), `404` (show/reply/archive), `419`
  (CSRF), `500` (filtro `unread`; falha de `LayoutBaseConfig`), `401/403` (AJAX).
- **Limites**: 10.000 (mensagem/resposta), 255 (nome/e-mail/assunto), 16 (telefone), 20 por
  página, sem throttle.
- **Dados pessoais**: nome, e-mail, telefone, IP, UA e conteúdo ficam no banco e no
  `v2_mail_logs` (corpo); não há mascaramento nem retenção definida.

## 12. Seeds e dados iniciais

Pertencem a `DATA-SEEDS-BASICPAGES`:

- `FaleConoscoSeeder` cria/atualiza uma linha em `v2_basic_pages` com slug `fale-conosco`,
  título `Fale Conosco — SUCESU Nacional`, `is_runtime=true`, HTML com hero, contatos fixos
  (telefone `(81) 99602-4167`, endereço em Brasília, horário `8:00 – 17:00`), formulário
  `action="#" id="contact-form"` e `div.g-recaptcha` com
  `config('services.recaptcha.site_key','6Lc_AAAAAAA1W_A')`; imagem de breadcrumb via galeria;
  idempotência por `slug` (`FaleConoscoSeeder.php:10-107`).
- **Essa página é sombreada pela rota do módulo**: as rotas de módulo são registradas antes
  do fallback `/{slug}`, então `/fale-conosco` sempre executa o controller e a linha fica
  inalcançável por essa URL (conteúdo legado).
- **Nenhum seeder** cria `contato_recipient_email`/`contato_auto_reply_*`; sem essas chaves,
  nenhum e-mail é enviado.

## 13. Lacunas

- `LG-FALECONOSCO-01` — Quem/como grava `contato_recipient_email` e `contato_auto_reply_*`:
  não há formulário no corpus. Procurar em scripts SQL, `v2_portal_configs` de produção ou
  telas futuras do SLE. Impacto: alto (sem as chaves, não há e-mail).
- `LG-FALECONOSCO-02` — Se existia widget de reCAPTCHA na versão antiga da página (o
  `BasicPage` semeado tem, a view do módulo não). Procurar em layouts/JS antigos e no
  `REFERENCE/`. Impacto: médio (spam).
- `LG-FALECONOSCO-03` — Por que `Request::boolean()` (5.6+) foi usado com Laravel 5.5: pode
  haver um macro registrado em runtime; não foi localizado. Procurar em
  `AppServiceProvider`/macros. Impacto: alto (500 no filtro).
- `LG-FALECONOSCO-04` — Destino/aplicação do `user_agent` e do `ip_address` (nenhuma tela
  além do IP no detalhe). Impacto: baixo.
- `LG-FALECONOSCO-05` — Política de retenção de `v2_mail_logs` (corpo completo) e de
  mensagens arquivadas. Impacto: privacidade/LGPD.
- `LG-FALECONOSCO-06` — Comportamento quando `v2_layout_base_configs` não existe (erro 500
  vs payload vazio): não há `try/catch`. Impacto: médio.
- `LG-FALECONOSCO-07` — Uso real da tabela `v2_contato_configs` em produção (pode ter dados
  legados). Impacto: baixo.

## 14. Checklist de paridade

- [ ] `PC-FALECONOSCO-01` — `GET /fale-conosco` renderiza formulário com 5 campos e cartão
      de informações vindo de `LayoutBaseConfig(key='contato')`.
- [ ] `PC-FALECONOSCO-02` — Validação exata: `name`/`email`/`subject`/`message` obrigatórios,
      `email` válido, `phone` opcional com regex `^\([0-9]{2}\)\s[0-9]{4,5}-[0-9]{4}$`,
      `message` ≤10.000.
- [ ] `PC-FALECONOSCO-03` — POST válido grava a linha com IP/UA e redireciona com
      `Mensagem enviada com sucesso! Entraremos em contato em breve.`.
- [ ] `PC-FALECONOSCO-04` — Notificação interna só quando `contato_recipient_email` não
      vazio; assunto `[Contato] {subject}`; corpo com os campos e `nl2br(e(message))`.
- [ ] `PC-FALECONOSCO-05` — Auto-resposta só quando `contato_auto_reply_body` não vazio;
      assunto configurável ou `Recebemos sua mensagem`.
- [ ] `PC-FALECONOSCO-06` — Falha de e-mail não altera a resposta ao usuário; registro
      `failed` em `v2_mail_logs` e log de erro.
- [ ] `PC-FALECONOSCO-07` — reCAPTCHA validado apenas se o campo existir; falha exibe
      `Falha na verificação do reCAPTCHA. Tente novamente.` e repopula o form.
- [ ] `PC-FALECONOSCO-08` — Inbox com busca (nome/e-mail/assunto), badge de não lidas,
      20/página, ordenação desc.
- [ ] `PC-FALECONOSCO-09` — Abrir mensagem marca `is_read=true` e audita `read`.
- [ ] `PC-FALECONOSCO-10` — Responder grava `reply_body`/`replied_at`, tenta `Re: {subject}`
      e exibe `Resposta enviada com sucesso!` independentemente do resultado.
- [ ] `PC-FALECONOSCO-11` — Arquivar grava `is_archived=true`, audita e remove da inbox com
      `Mensagem arquivada com sucesso!`.
- [ ] `PC-FALECONOSCO-12` — Decidir e documentar o comportamento do filtro “Apenas não
      lidas” (corrigir o 500 ou reproduzir).
- [ ] `PC-FALECONOSCO-13` — `/fale-conosco` fora do page cache e do cache HTTP; `robots.txt`
      com `Disallow: /fale-conosco`; sem entrada no sitemap.
- [ ] `PC-FALECONOSCO-14` — Dashboard mostra “Mensagens Não Lidas” com `inbox()->unread()`
      quando o módulo está ativo.
- [ ] `PC-FALECONOSCO-15` — RBAC `FaleConosco`: `read` vê, `write` responde/arquiva.

## 15. Evidências consultadas

- `V2/Modules/Institucional/FaleConosco/Routes/cms.php:1-31`; `Routes/web.php:1-16`.
- `V2/Modules/Institucional/FaleConosco/ModuleProvider.php:1-37`.
- `V2/Modules/Institucional/FaleConosco/Models/MensagemContato.php:1-118`;
  `Models/ContatoConfig.php:1-49`.
- `V2/Modules/Institucional/FaleConosco/Migrations/2024_01_01_000007_create_v2_mensagens_contato_table.php:1-86`;
  `...000008_create_v2_contato_configs_table.php:1-71`.
- `V2/Modules/Institucional/FaleConosco/Controllers/FaleConoscoPortalController.php:1-165`;
  `Controllers/FaleConoscoCmsController.php:1-154`.
- `V2/Modules/Institucional/FaleConosco/Views/portal/index.blade.php:1-221`;
  `Views/cms/inbox.blade.php:1-124`; `Views/cms/show.blade.php:1-118`.
- `V2/Services/MailService/MailService.php:39-134,360-380`; `MailResult.php:14-59`.
- `V2/Modules/Support/StructuralLandingEditor/Controllers/LayoutBaseCmsController.php:185-199,250-262`;
  `Views/cms/tabs/layoutbase/contato.blade.php:1-101`;
  `Models/LayoutBaseConfig.php:1-40`.
- `V2/Core/Providers/V2ServiceProvider.php:203-224,293-307`;
  `V2/Core/Middleware/PageCacheMiddleware.php:16-23`;
  `V2/Core/Middleware/PublicCacheMiddleware.php:31-36`;
  `V2/Core/Middleware/CmsAuthenticate.php:1-46`;
  `V2/Core/Middleware/V2PermissionMiddleware.php:1-137`.
- `V2/Services/SEO/Controllers/SeoPortalController.php:35-55`;
  `V2/Services/Dashboard/DashboardStatsService.php:93-105,660-675`;
  `V2/Seeds/BasicPages/FaleConoscoSeeder.php:1-110`;
  `config/v2.php:1-94`; `composer.json:15`; `public/assets/js/masks.js:39-60`.
