# Editor Estrutural / Landing Sections Editor — Resumo Executivo

> **Versão analisada:** camada `V2/` do repositório `lotep/` (Laravel 5.5.50, PHP 7.4.33)
> **Slug do módulo:** `support/StructuralLandingEditor` (dossiê: `support-structurallandingeditor`)
> **Serviço acoplado:** `V2/Services/LandingSectionsEditor` (dossiê no mesmo diretório)
> **Natureza:** módulo de suporte (grupo `Support`) + serviço de UI/renderização de seções
> **Estado:** em produção no CMS; um bloco de testes de feature está inteiramente desativado

Todos os caminhos abaixo são relativos à raiz `lotep/`.

---

## 1. Objetivo

O módulo dá ao **suporte técnico** controle direto sobre a "casca" do portal público — header,
footer, barras laterais, CSS/JS globais, logos, links, contato, redes sociais, LAI, metadados/SEO,
tema e flags de acessibilidade — sem deploy. Além disso, a partir do plano `plan/027`, ele edita a
**Página Inicial** como uma lista ordenada de seções (`homepage_sections`, versão 3), usando o
serviço `LandingSectionsEditor` como catálogo de widgets, formulários, validação e preview.

O serviço `LandingSectionsEditor` é reutilizado por outros módulos (a home de `BasicPage` e as
Páginas Customizadas) para renderizar seções modulares e resolver imagens da galeria.

---

## 2. Efeito / Impacto

| Faixa | Efeito |
|---|---|
| Cidadão | Vê header/footer/CSS/JS e a home definidos pelo suporte; seções da home podem ser reordenadas, ocultadas ou trocadas por comunicado/HTML. |
| Prefeitura (CMS) | O suporte altera a estrutura do portal em tempo real, com auditoria por gravação de config. |
| Transparência e legalidade | LAI e comunicado global são dados editáveis; porém o conteúdo é HTML livre, sem trilha editorial formal. |
| Operação técnica | Um único e-mail (`config('v2.support.email')`) concentra todo o poder de editar HTML/Blade executado no portal. |

---

## 3. Comportamento

- **Áreas únicas de conteúdo.** `v2_structural_portal_contents` tem uma linha por área (`area` é
  `UNIQUE`): `header`, `main_left`, `main_right`, `footer`, `css_head`, `css_foot`, `js_head`,
  `js_foot` (`V2/Modules/Support/StructuralLandingEditor/Migrations/2026_07_03_000000_create_v2_structural_portal_blocks_table.php:22-30`).
- **Fallback governamental.** Área vazia ou inativa faz o layout incluir o componente padrão
  (`V2/layouts/portal/partials/portal-content.blade.php:18-40` e `:119-137`).
- **Conteúdo é Blade.** O texto salvo é compilado por `BladeCompiler::compileString()` e incluído
  como PHP (`V2/Modules/Support/StructuralLandingEditor/Services/BlockRenderer.php:156-203`).
- **Home versionada.** `v2_layout_base_configs.payload` guarda
  `{version: 3, sections: [{id, type, parameters, hide?}]}` sob a chave `homepage_sections`
  (`V2/Modules/Support/StructuralLandingEditor/Services/HomepageSectionsService.php:19-22`).
- **Whitelist de seções.** Só entram na ordem os tipos de `ALL_TYPES` (9), `OPTIONAL_TYPES`
  (`home-jogos-autorizados`) e `home-comunicado`; `home-header` é extraído para fora da ordem
  (`HomepageSectionsService.php:194-240`).
- **Parâmetros só para estáticas.** `STATIC_TYPES` expõem `parameters` para a view; seções dinâmicas
  (`home-imprensa`, `home-dashboard`, `home-agenda`, `home-jogos-autorizados`) são apenas marcadores
  de posição — os dados vêm de `HomepageDataService::build()`.
- **`hide` preserva posição.** A seção continua na ordem e com parâmetros salvos, mas é listada em
  `hidden` e o Blade da home a ignora (`HomepageSectionsService.php:225-231`;
  `V2/Modules/Institucional/BasicPage/Views/portal/homepage.blade.php:94-103`).
- **Sem configuração = layout default.** `parseConfig(null)` devolve `order = ALL_TYPES`, sem
  overrides (`HomepageSectionsServiceTest::test_parse_config_without_config_returns_defaults`).
- **Sanitização por widget.** O editor e o salvamento chamam `sanitizeContent()`; o padrão é
  `strip_tags` recursivo, mas `html-free`, `home-comunicado` e `bloco-sle` têm sanitize próprio
  (`V2/Services/LandingSectionsEditor/Widgets/BaseWidget.php:62-72`).
- **Preview em cache.** O editor envia as seções para `POST /cms/v2/landing-sections/preview/save`
  com um `token`; o iframe lê `GET /cms/v2/landing-sections/preview/render?token=TOKEN`, com TTL de 1 hora
  (`V2/Services/LandingSectionsEditor/Controllers/LandingSectionsEditorController.php:133-171`).

---

## 4. Como o Usuário Interage

O menu do CMS expõe o módulo apenas para o e-mail de suporte
(`V2/Modules/Support/StructuralLandingEditor/ModuleProvider.php:36-40`), com seis submódulos e uma
biblioteca de arquivos:

| Submódulo | Rota | Tela |
|---|---|---|
| Metaconfigurações | `/cms/infra/structural-editor/meta` | metadados, SEO, e-mail |
| Tema Visual Global | `/cms/infra/structural-editor/theme` | tema do portal/CMS, logos, banner global |
| Dados Estruturais | `/cms/infra/structural-editor/structural-data` | links de header/footer, contato, redes, LAI |
| Página Inicial | `/cms/infra/structural-editor/homepage` | editor de seções com reordenação e preview |
| Features | `/cms/infra/structural-editor/features` | VLibras, barra/widget de acessibilidade, LAI |
| Editor | `/cms/infra/structural-editor/editor` | HTML/Blade de header, barras, footer, CSS/JS |
| Biblioteca de Arquivos | `/cms/infra/structural-editor/editor/assets` | upload de CSS, JS e imagens + snippet |

O editor de seções (componente compartilhado) abre um modal por tipo, valida via AJAX
(`/cms/v2/landing-sections/validate`), renderiza uma seção isolada
(`/render-section`) e atualiza o iframe por `postMessage`.

---

## 5. Detalhes e Particularidades Técnicas

- **Duas superfícies HTTP.** O módulo registra rotas em `Routes/cms.php` com
  `CmsAuthenticate` + `v2.permission:structural-landing-editor`; o serviço registra
  `Routes/cms.php` com **apenas** `CmsAuthenticate`
  (`V2/Services/LandingSectionsEditor/Routes/cms.php:10-23`). O Core monta rotas de serviço só com
  `web` (`V2/Core/Providers/V2ServiceProvider.php:391-395`), portanto **sem RBAC**.
- **Permissão declarada não é usada.** `V2PermissionMiddleware` ignora o parâmetro da rota e resolve
  o módulo pelo primeiro `active_pattern` que casar
  (`V2/Core/Middleware/V2PermissionMiddleware.php:38-48`).
- **Gate duplo por e-mail.** Além do middleware, cada ação de `SleCmsController` chama
  `authorizeSupportAccess()` (`SleCmsController.php:35-40`).
- **Registro de widgets é estático.** `WidgetRegistry::$widgets` é um array estático preenchido sob
  demanda (`V2/Services/LandingSectionsEditor/Services/WidgetRegistry.php:9-50`); há 35 widgets
  registrados e 31 classes de schema.
- **Preparação em lote.** `prepareSections()` coleta IDs de anexos de todos os widgets e faz **uma**
  consulta `whereIn` em `v2_gallery_media`
  (`V2/Services/LandingSectionsEditor/Services/LandingSectionsEditorRendererService.php:309-382`).

---

## 6. Estrutura de Dados

| Tabela | Papel | Destaques |
|---|---|---|
| `v2_structural_portal_contents` | conteúdo por área do layout | `area` varchar(30) UNIQUE; `content` text (HTML/Blade); `content_type`; `active` |
| `v2_layout_base_configs` | configurações estruturais chave-valor | `key` UNIQUE; `payload` jsonb; `transaction_snapshot_id`; soft delete |
| `v2_sle_assets` | biblioteca de CSS/JS/imagens do editor | `type`; `storage_path`; `gallery_media_id`; `snippet` text com Blade |

Chaves conhecidas em `v2_layout_base_configs`: `logos`, `links_header`, `links_footer`, `contato`,
`social_media`, `lai_items`, `lai_enabled`, `global_banner`, `homepage_sections`.

---

## 7. Como Testar

| Nível | Arquivo | Situação |
|---|---|---|
| Feature | `tests/Feature/V2/LandingSectionsEditorTest.php` | **6 testes, todos `markTestSkipped` no `setUp`** |
| Unit | `tests/Unit/V2/Modules/Support/StructuralLandingEditor/HomepageSectionsServiceTest.php` | 11 casos do contrato v3 |
| Unit | `tests/Unit/V2/Modules/Support/StructuralLandingEditor/BlockRendererSandboxTest.php` | 3 casos, compara sandbox com `view()->make` |
| Unit | `tests/Unit/V2/Modules/Support/StructuralLandingEditor/SleCmsControllerTest.php` | 9 casos de `saveEditor`/gate |
| Unit | `tests/Unit/V2/Services/LandingSectionsEditor/HomeComunicadoWidgetTest.php` | 1 caso de sanitize |
| Unit | `tests/Unit/V2/Services/LandingSectionsEditor/HomeJogosAutorizadosWidgetTest.php` | 2 casos de registro/render |

Comando: `vendor/bin/phpunit tests/Unit/V2/Modules/Support/StructuralLandingEditor tests/Unit/V2/Services/LandingSectionsEditor`.

---

## 8. Migração para Laravel Moderno

O V7 **não porta HTML/Blade como dado**: as áreas passam a ser **slots + JSON de blocos** (ADR-016,
ADR-017). O que sobrevive é o contrato de **seções ordenadas** (`version/sections/parameters/hide`),
o **registry de tipos** e a **preparação em lote de mídias**; o que cai é o editor de código livre,
o `BlockRenderer` (`compileString` + `include`) e o gate por e-mail fixo. Detalhes e justificativas
em `06-MIGRACAO-MODERNA.md` e `09-APROVEITAMENTO-V7.md`.

---

## 9. Resumo Geral

Este dossiê cobre o par módulo+serviço que transforma o portal da LOTEP em uma tela editável pelo
suporte. O módulo é o CMS: sete telas no total (seis submódulos + biblioteca de assets), oito áreas de
conteúdo em banco, nove chaves de configuração e uma biblioteca de assets. O serviço é o motor de seções: 35 widgets, 31 schemas de validação,
sanitização por tipo, preview em cache e resolução de imagens em lote. O desenho funciona, mas
descansa em três decisões que o V7 não aceita: **HTML/Blade no banco** (execução de PHP a partir de
dado), **sanitização por `strip_tags`/regex** e **autorização por e-mail fixo**. A home versionada
(v3) e o registry de widgets são o ativo reaproveitável; a forma de persistir e renderizar precisa
ser trocada por JSON estruturado + componentes Blade de código.

---

## Índice do dossiê

| Arquivo | Conteúdo |
|---|---|
| `00-RESUMO.md` | Este documento |
| `01-ARQUITETURA.md` | Camadas, classes, fluxo de requisição e fronteiras |
| `02-MODELAGEM.md` | Tabelas, payloads, migrations e seeds |
| `03-ROTAS-E-CONTROLADORES.md` | Rotas, controllers, validação e autorização |
| `04-VIEWS-E-UX.md` | Telas, componente do editor, preview e renders |
| `05-REGRAS-E-PORTABILIDADE.md` | Regras não óbvias, armadilhas e acoplamentos |
| `06-MIGRACAO-MODERNA.md` | Schema, modelos, catálogo, validação e policies no V7 |
| `06b-ENDPOINTS-E-COMPONENTES.md` | Endpoints, views, cache, riscos e ordem de implementação |
| `07-TESTES.md` | Estratégia, casos existentes e cobertura proposta |
| `08-GAPS-E-DIVIDAS.md` | Bugs, riscos, dívida e perguntas abertas |
| `09-APROVEITAMENTO-V7.md` | Portar / adaptar / rejeitar, com ADRs |
