# Família Acolhedora - pendências de correção (Gustavo)

Revisão do formulário público em `resources/views/paginas/formularios/familia-acolhedora/index.blade.php` e camadas associadas (`FamiliaAcolhedoraRequest`, `FamiliaAcolhedoraController`, `FamiliaAcolhedoraMail`, template de e-mail).

**Escopo deste documento:** correções de código e configuração. A ativação/publicação da rota fica fora do escopo (decisão deliberada de segurança até o módulo estar endurecido).

**Referência de implementação correta no projeto:** formulário Fale Conosco do MobiAngra (`MobiangraManifestacaoRequest` + `MobiangraController::faleConoscoStore`).

**Guia geral de formulários por e-mail:** `docs/manuais-formularios/formulario-email.md`

---

## O que já está adequado (não refatorar sem necessidade)

- `FormRequest` dedicada com `validated()` no controller
- `@csrf` no formulário
- Escape com `{{ }}` na view e no e-mail
- Termo LGPD obrigatório (`termo_lgpd` com `accepted`)
- i18n com `__()` na maior parte dos textos visíveis
- CSS parcial em arquivo separado (`public/pmar/css/familia-acolhedora.css`)
- Widget reCAPTCHA na interface (quando `config('recaptcha.enabled')` é verdadeiro)

---

## 1. reCAPTCHA validado apenas no navegador (crítico)

**Arquivos:** `FamiliaAcolhedoraRequest.php`, `FamiliaAcolhedoraController.php`

**Problema:** a view exibe o reCAPTCHA e desabilita o botão até o callback JavaScript, mas o servidor **não valida** `g-recaptcha-response`. A Request não inclui essa regra e o controller não chama `$this->recaptcha()`.

**Por quê é falha:** qualquer cliente HTTP (curl, script, bot) pode enviar `POST` direto para o endpoint ignorando o captcha. Proteção só no front-end não é proteção.

**Riscos:**

- Spam em massa de inscrições falsas
- Sobrecarga do servidor de e-mail (SMTP) e possível bloqueio da conta institucional
- E-mails com dados pessoais falsos ou lixo enchendo a caixa do setor (`seas.familiaacolhedora@angra.rj.gov.br`)
- Custo operacional da equipe para triar envios inválidos

**Correção:**

1. Na Request, incluir (padrão MobiAngra):

   ```php
   'g-recaptcha-response' => [config('recaptcha.enabled') ? 'required' : 'nullable', 'string'],
   ```

2. No `store()`, antes do envio:

   ```php
   if (config('recaptcha.enabled') && ! $this->recaptcha($request->input('g-recaptcha-response'))) {
       return redirect()
           ->route('paginas.familiaacolhedora.create')
           ->withInput()
           ->with('error', __('Verificação de segurança inválida. Tente novamente.'));
   }
   ```

3. Não repassar `g-recaptcha-response` para o Mailable (usar `except` ou apenas `$request->validated()` sem esse campo no array enviado ao e-mail).

4. Exibir `@if(session('error'))` na view (hoje só há `success`).

**Regra do projeto:** regra 27 (`rules.mdc`) - proteção contra abuso em endpoints públicos.

---

## 2. Rate limiting no POST (alto)

**Arquivo:** definição da rota POST (quando for publicada)

**Problema:** a rota POST não usa `middleware('throttle:web-public')`, ao contrário de outros endpoints públicos do portal (ex.: `boletim-oficial-ajax`, `legislacao`).

**Por quê é falha:** sem limite de requisições por IP, um atacante pode automatizar centenas de envios por minuto mesmo com captcha (ou explorar janelas em que o captcha estiver desabilitado em homologação).

**Riscos:**

- Ataque de negação de serviço leve contra o SMTP da prefeitura
- Bloqueio/blacklist do provedor de e-mail institucional
- Indisponibilidade do formulário para cidadãos legítimos

**Correção:** ao publicar o POST, aplicar:

```php
->middleware('throttle:web-public');
```

**Regra do projeto:** regra 27 (`rules.mdc`).

---

## 3. Campos de opção sem whitelist (`Rule::in`) (médio)

**Arquivo:** `FamiliaAcolhedoraRequest.php`

**Problema:** `disponibilidade` e `como_soube` aceitam qualquer `string`. Os valores válidos existem só nos radios da view, mas não são enforced no servidor.

**Por quê é falha:** a validação deve refletir o domínio permitido. Confiar apenas no HTML do formulário permite manipular o POST.

**Riscos:**

- Dados inconsistentes no e-mail recebido pelo setor (valores inventados, textos longos ou caracteres estranhos)
- Dificuldade de relatório/agregação futura se os dados forem persistidos
- Vetor menor de injeção de conteúdo inesperado no corpo do e-mail

**Correção:** usar `Illuminate\Validation\Rule::in()` com os valores exatos dos radios:

- `disponibilidade`: `Manhã`, `Tarde`
- `como_soube`: `Propaganda em ônibus`, `TV/Jornal`, `Rádio`, `Cartaz/Panfletagem`, `Indicação de alguém`, `Outros`

---

## 4. Validação condicional de `indicacao` e `outros` (médio)

**Arquivo:** `FamiliaAcolhedoraRequest.php`

**Problema:** quando o usuário marca "Indicação de alguém" ou "Outros", os campos de texto associados são opcionais no servidor. O JavaScript da view esconde/limpa os inputs, mas isso não vale para requisições forjadas.

**Por quê é falha:** regra de negócio incompleta - o setor recebe inscrições sem a informação que o próprio formulário declara necessária naquele contexto.

**Riscos:**

- Cadastros incompletos que exigem retrabalho da equipe (contato para complementar)
- Dados enganosos no e-mail (opção selecionada sem detalhe)

**Correção:** em `rules()`, usar validação condicional:

- se `como_soube` = `Indicação de alguém` -> `indicacao` `required`
- se `como_soube` = `Outros` -> `outros` `required`
- caso contrário -> `indicacao` e `outros` `nullable` (ou `prohibited`)

---

## 5. Destino de e-mail sem garantia de configuração (médio)

**Arquivos:** `FamiliaAcolhedoraController.php`, `config/mail.php`, `.env`

**Problema:** `Mail::to(config('mail.formularios.familia_acolhedora_destino'))` depende de `MAIL_FORM_FAMILIA_ACOLHEDORA_DESTINO`. Se a variável estiver vazia, o envio ao setor falha.

**Por quê é falha:** formulário público com PII não pode depender de config implícita sem validação na subida ou no runtime.

**Riscos:**

- HTTP 500 para o cidadão após preencher todo o formulário
- Perda silenciosa da inscrição (cidadão acha que enviou; setor não recebe)
- Exposição de stack trace se `APP_DEBUG=true` em ambiente inadequado

**Correção:**

- Documentar a variável no `.env.example`
- Validar no controller (ou Service) antes do `Mail::to`: se destino vazio, logar erro e retornar mensagem amigável sem vazar detalhe técnico
- Confirmar valor correto em homologação antes de publicar

---

## 6. Ausência de tratamento de exceções no envio (médio)

**Arquivo:** `FamiliaAcolhedoraController.php`

**Problema:** não há `try/catch` em torno de `Mail::send()`. Falha de SMTP, timeout ou credencial inválida gera exceção não tratada.

**Por quê é falha:** regra 10 do projeto exige mensagem amigável ao usuário e log interno.

**Riscos:**

- Experiência ruim: tela de erro genérica após envio
- Cidadão não sabe se deve tentar de novo
- Equipe sem rastro em log para diagnosticar falha de e-mail

**Correção:** padrão MobiAngra - `try/catch` com `Log::error()` (sem dados sensíveis no log: não registrar CPF, e-mail completo, endereço) e redirect com `with('error', __('...'))`.

---

## 7. `messages()` ausente na FormRequest (baixo)

**Arquivo:** `FamiliaAcolhedoraRequest.php`

**Problema:** só existe `attributes()`. Mensagens de erro usam os defaults do Laravel (nem sempre amigáveis ou traduzidos).

**Por quê é falha:** padrão do projeto para formulários públicos (ver `MobiangraManifestacaoRequest::messages()`).

**Riscos:**

- Mensagens técnicas ou em inglês para o cidadão
- Piora de acessibilidade e confiança no serviço público digital

**Correção:** adicionar `messages()` com strings via `__()`, incluindo mensagem específica para `g-recaptcha-response.required` e `termo_lgpd.accepted`.

---

## 8. Sem `prepareForValidation()` (baixo)

**Arquivo:** `FamiliaAcolhedoraRequest.php`

**Problema:** entradas não são normalizadas (trim de espaços, campos vazios convertidos em `null`).

**Por quê é falha:** dados com espaços à frente/trás passam na validação mas poluem o e-mail e dificultam busca futura.

**Riscos:** baixo, mas gera ruído operacional.

**Correção:** `trim()` nos campos de texto antes das regras (padrão MobiAngra).

---

## 9. CSS inline na view (front-end / padrão do projeto)

**Arquivo:** `resources/views/paginas/formularios/familia-acolhedora/index.blade.php`

**Problema:** atributos `style="max-width: ..."` em várias imagens.

**Por quê é falha:** regra 5 de `rules.mdc` proíbe CSS inline em views; assets devem ficar em `public/pmar/css/familia-acolhedora.css`.

**Riscos:** não é vulnerabilidade de segurança direta, mas viola padrão institucional, dificulta manutenção e revisão de segurança (código espalhado).

**Correção:** mover limites de largura para classes no CSS existente.

---

## 10. JavaScript inline na view (front-end / padrão do projeto)

**Arquivo:** `index.blade.php` (`@push('scripts')`, linhas ~263-289)

**Problema:** lógica de `recaptchaCallback` e toggle de `indicacao`/`outros` está inline na Blade.

**Por quê é falha:** regra 5 - JS deve ficar em `public/pmar/js/` (ex.: `public/pmar/js/familia-acolhedora.js`), carregado condicionalmente como o CSS no `head.blade.php`.

**Riscos:** manutenção e auditoria mais difíceis; em políticas CSP futuras, inline script seria bloqueado.

**Correção:** extrair para arquivo JS dedicado e referenciar com `asset()`.

---

## 11. Acessibilidade nos grupos de radio (baixo)

**Arquivo:** `index.blade.php`

**Problema:** grupos "Disponibilidade" e "Como soube" não usam `<fieldset>` + `<legend>`. Erros de validação desses campos não aparecem com `@error`.

**Por quê é falha:** regra 9 (WCAG) do projeto.

**Riscos:** usuários de leitor de tela podem não associar labels aos grupos; erros de validação podem passar despercebidos.

**Correção:** envolver cada grupo em `fieldset`/`legend` e exibir feedback de erro acessível (`role="alert"` ou `@error`).

---

## 12. Regra de negócio: maioridade legal (sugestão)

**Arquivo:** `FamiliaAcolhedoraRequest.php`

**Problema:** a página informa que é exigida maioridade legal, mas `data_nascimento` só valida `date` - aceita qualquer data, inclusive futura ou de menor.

**Por quê importa:** inconsistência entre o que o serviço promete e o que o sistema aceita.

**Riscos:**

- Inscrições de menores que serão reprovadas manualmente (retrabalho)
- Não é fraude grave, mas afeta qualidade do fluxo

**Correção (opcional, alinhar com a equipe SDSP):** `before_or_equal` com data de 18 anos atrás e `after` com limite razoável (ex.: não aceitar datas futuras).

---

## Checklist antes de pedir publicação da rota

| Item | Prioridade |
|------|------------|
| reCAPTCHA validado no servidor | Crítica |
| `throttle:web-public` no POST | Alta |
| `Rule::in` em `disponibilidade` e `como_soube` | Média |
| Validação condicional `indicacao` / `outros` | Média |
| `MAIL_FORM_FAMILIA_ACOLHEDORA_DESTINO` configurado e validado | Média |
| `try/catch` + log no envio de e-mail | Média |
| `messages()` na Request | Baixa |
| `prepareForValidation()` | Baixa |
| CSS/JS fora da Blade | Padrão do projeto |
| A11y nos radios | Baixa |
| Validação de maioridade (se acordado com negócio) | Sugestão |

---

## Arquivos envolvidos

| Caminho | Papel |
|---------|--------|
| `app/Http/Requests/Paginas/Formularios/FamiliaAcolhedoraRequest.php` | Validação |
| `app/Http/Controllers/Paginas/Formularios/FamiliaAcolhedoraController.php` | Orquestração e envio |
| `app/Mail/Formularios/FamiliaAcolhedoraMail.php` | E-mail |
| `resources/views/paginas/formularios/familia-acolhedora/index.blade.php` | Formulário |
| `resources/views/emails/formularios/familia-acolhedora.blade.php` | Corpo do e-mail |
| `public/pmar/css/familia-acolhedora.css` | Estilos |
| `config/mail.php` | Destino `familia_acolhedora_destino` |

---

*Documento gerado em revisão de conformidade com `.cursor/rules/rules.mdc` (segurança e front-end).*
