# Gaps, Dívidas e Riscos — Editor Estrutural + Landing Sections Editor

> Caminhos relativos à raiz `lotep/`. Severidade: **crítica** (segurança/perda de dados),
> **alta** (função quebrada), **média** (degradação), **baixa** (code smell).

---

## 1. Bugs e erros conhecidos

| ID | Severidade | Descrição | Onde | Impacto |
|---|---|---|---|---|
| B-01 | crítica | `render-section` executa `bloco-sle` para **qualquer usuário autenticado**: o gate do render só vale quando a rota é `preview.render` | `V2/Services/LandingSectionsEditor/Views/render/bloco-sle.blade.php:12-31`; `Controllers/LandingSectionsEditorController.php:213-268` | execução remota de PHP/Blade a partir de um POST |
| B-02 | alta | `json_decode` inválido no editor de links/redes/LAI vira `[]` e apaga a configuração | `LayoutBaseCmsController.php:190-201`, `:235-260` | perda de menus/LAI sem erro |
| B-03 | alta | `json_decode` inválido em `homepage_sections_json` vira lista vazia e grava home sem seções | `LayoutBaseCmsController.php:305-311` | home em branco (fallback? `order=[]`, não default) |
| B-04 | alta | Duplicar o mesmo `type` na lista não é bloqueado; a ordem renderiza a seção duas vezes e `sections[type]` guarda só a última | `HomepageSectionsService.php:194-240`; `homepage.blade.php:94-103` | conteúdo duplicado/inconsistente |
| B-05 | alta | `saveHomepage` audita `new` como a string JSON **não sanitizada**, divergindo do payload gravado | `SleCmsController.php:282-286` | trilha de auditoria não corresponde ao estado |
| B-06 | média | Widget `video` usa `VideoPlaylistSchema` | `LandingSectionsEditorRendererService.php:73-75` | validação errada para embed |
| B-07 | média | `saveTheme` captura `$oldLayoutConfigs` e nunca usa | `SleCmsController.php:143-145` | auditoria incompleta de logos/banner |
| B-08 | média | Upload de asset não-AJAX redireciona sempre para a tela `editor`, mesmo vindo da biblioteca | `SleCmsController.php:545-547` | UX inconsistente |
| B-09 | média | `tab` ausente/desconhecido em `LayoutBaseCmsController::update` retorna sem erro; o chamador exibe "salvo" | `LayoutBaseCmsController.php:36-72`; `SleCmsController.php:84-101` | falso positivo de gravação |
| B-10 | média | `saveEditor` audita `content_type` como `htmlmixed` quando o campo é omitido, mesmo para área CSS/JS | `SleCmsController.php:463-471` | auditoria divergente do banco |
| B-11 | média | `prepareSections` resolve mídia com `deleted_at` não nulo | `LandingSectionsEditorRendererService.php:339-348` | imagem arquivada continua pública |
| B-12 | baixa | `getBlocks()` devolve `Collection` de 1 item "para compatibilidade", mas o layout itera | `BlockRenderer.php:58-66` | API enganosa |
| B-13 | baixa | `LayoutBaseComposer` usa `static $layoutConfigs` | `ViewComposers/LayoutBaseComposer.php:16-26` | config velha em runtime de longa duração (Octane) |
| B-14 | baixa | `WidgetRegistry::register` sobrescreve silenciosamente o mesmo tipo | `WidgetRegistry.php:18-21` | perda de definição |
| B-15 | baixa | `MediaAuditSubject` é um model sem tabela usado só como sujeito de auditoria | `Models/MediaAuditSubject.php:12-21` | model "fake" no domínio |

---

## 2. Funcionalidades incompletas ou mortas

| Item | Evidência | Consequência |
|---|---|---|
| Testes de feature do serviço | `LandingSectionsEditorTest.php:29-33` marca **todos** como skipped | nenhuma cobertura de endpoints |
| Rota `v2.layout-base.update` | citada no teste e em `tests/Feature/V2/LandingSectionsEditorTest.php:225`, não existe em `Routes/cms.php` | teste impossível de rodar |
| `transaction_snapshot_id` | coluna em `v2_layout_base_configs`; só mencionada em texto de tela | histórico por transação não implementado |
| Alias `v2.structural-editor.index` | `Routes/cms.php:68` | rota duplicada sem uso identificado |
| `Views/render/0.blade.php` | não referenciado pelo registry nem por `renderSection` | view órfã |
| `Views/cms/tabs/userconfigs/temas.blade.php` | nenhum `@include` aponta para ela | tela órfã |
| `ValidationSchemas/VideoSchema.php` | o widget `video` é registrado com `VideoPlaylistSchema` | schema nunca aplicado |
| Editor manual com exemplos de `sle_component()` | `Views/manual/content.blade.php:302-314` | documenta um recurso que o V7 não terá |
| `resetCmsTheme()` | `UserConfigsCmsController.php:46-55`; sem rota no módulo | método inalcançável por HTTP |
| Botão de upload de JS/CSS | biblioteca de assets | funcionalidade perigosa mantida |

---

## 3. Itens divergentes entre versões

Não há versão anterior equivalente na V2. A V1 possui apenas um teste de permissão de landing page
(`tests/Feature/V1/LandingPageCmsPermissionTest.php`), sem o editor estrutural.

### 3.1 Removido na versão atual

Não se aplica: não há versão anterior deste módulo.

### 3.2 Novo na versão atual

| Item | Substitui o quê? |
|---|---|
| Homepage versionada v3 (`homepage_sections`) | lista sem versão |
| Seções dinâmicas como marcadores (`home-imprensa`, `home-dashboard`, `home-agenda`) | conteúdo estático no Blade |
| `home-jogos-autorizados` opt-in | seção fora da home |
| Widgets `home-*` com `imageSpecs` | resolução manual de imagens |
| `bloco-sle` | execução de template em páginas customizadas |

---

## 4. Mapa entre versões

| Aspecto | V1 | V2 | Equivalente? |
|---|---|---|---|
| Rotas do editor | não identificadas | `/cms/infra/structural-editor/*` | — |
| Rotas de seções | não identificadas | `/cms/v2/landing-sections/*` | — |
| Tabelas | — | `v2_structural_portal_contents`, `v2_layout_base_configs`, `v2_sle_assets` | — |
| Controllers | — | `SleCmsController`, `LayoutBaseCmsController`, `LandingSectionsEditorController` | — |
| Views | — | `v2-structurallandingeditor::cms.*`, `v2-service-landingsectionseditor::*` | — |
| Permissões | teste isolado de landing page | `v2.permission:structural-landing-editor` + e-mail | parcial |
| Home | Blade estático | config v3 + partials | não |

---

## 5. Riscos de dados na migração

| Risco | Tabela/campo | Verificação antes | Rollback |
|---|---|---|---|
| HTML/Blade em `content` não é convertível automaticamente | `v2_structural_portal_contents.content` | contar áreas ativas e classificar (`htmlmixed`/`css`/`javascript`) | manter coluna em backup; reescrever à mão |
| `homepage_sections` com tipos desconhecidos | `v2_layout_base_configs.payload` | `jsonb_array_elements` + agrupar `type` | manter payload original em `backup_*` |
| Mídias referenciadas por ID sem FK | `*_image_id` em params | `left join gallery_media` e listar órfãos | registrar órfãos antes de migrar |
| `snippet` contém Blade | `v2_sle_assets.snippet` | procurar `@include`, `{{`, `{!!` | não migrar; refazer via build |
| Config duplicada por soft delete | `v2_layout_base_configs.key` | `SELECT key, count(*) FROM v2_layout_base_configs GROUP BY key` incluindo deletados | limpar antes da UNIQUE nova |
| JSON inválido já gravado | `payload` | `jsonb_typeof(payload)` e tamanho | versionar cada payload importado |

Consulta de diagnóstico sugerida (somente leitura):

```sql
SELECT key, jsonb_typeof(payload) AS tipo, pg_column_size(payload) AS bytes
FROM v2_layout_base_configs
ORDER BY bytes DESC;
```

---

## 6. Dívida técnica

| Item | Tipo | Esforço | Risco de não corrigir |
|---|---|---|---|
| `BlockRenderer` (Blade do banco) | arquitetura/segurança | alto | RCE e impossibilidade de CSP |
| Três tabelas sem schema JSON | modelagem | médio | dados inválidos |
| Controladores chamando controladores | acoplamento | médio | testes frágeis |
| 31 schemas duplicando estrutura | manutenção | médio | divergência de regras |
| Duplicação de defaults (PHP + Blade) | manutenção | baixo | editor ≠ portal |
| Registry estático | testabilidade | baixo | estado entre testes |
| Consulta direta a `v2_gallery_media` | fronteira | médio | policies/soft delete ignorados |
| Auditoria dupla e divergente | observabilidade | baixo | trilha não confiável |
| Feature test desativado | qualidade | médio | regressões silenciosas |
| Upload de JS/CSS | segurança | baixo | script arbitrário same-origin |
| `array_set()` (helper removido no Laravel 6+) | portabilidade | baixo | quebra em upgrade |
| Sem paginação/filtro na lista de assets | performance | baixo | tela lenta |

---

## 7. Riscos de segurança

| Risco | Explorável por | Mitigação |
|---|---|---|
| Execução de Blade/PHP no portal | qualquer usuário autenticado no CMS via `render-section` + `bloco-sle` (B-01) | bloquear `bloco-sle` fora do suporte; remover o tipo no V7 |
| Execução de Blade armazenada | acesso ao banco, backup ou ao e-mail de suporte | não persistir template; ADR-017 |
| Gate por e-mail fixo | quem controla `V2_SUPPORT_EMAIL` ou a conta | RBAC ADR-033 + perfil protegido |
| Serviço sem RBAC | qualquer conta do CMS | middleware/Gate em todas as rotas |
| Upload de JS para o portal | suporte ou conta comprometida | proibir upload de JS; CSP |
| Favicon com MIME `octet-stream` | quem envia arquivo | validar assinatura, não só extensão/MIME |
| SVG em `image/*` | upload de imagem | sanitizar SVG ou bloquear |
| Preview token global | qualquer usuário que adivinhe/obtenha o token | token por sessão + TTL curto |
| Preview sem rate limit | autenticado | throttle |
| HTML em comunicado | suporte | AST TipTap + sanitização de saída |
| Inline `<script>` no portal/preview | qualquer visitante (CSP ausente) | CSP estática ADR-022 |
| Auditoria sem ator em eventos de serviço | — | incluir `user_id` na trilha ADR-035 |

---

## 8. Perguntas em aberto

| # | Pergunta | Quem decide | Impacto |
|---|---|---|---|
| 1 | O super-admin deve acessar o grupo `Support`? Hoje o bloqueio por grupo vem antes do bypass de super-admin | produto/segurança | define o Gate do V7 |
| 2 | O comunicado global ainda é necessário como HTML livre ou pode virar AST? | comunicação | define se `home.comunicado` usa RichText |
| 3 | Quem aprova mudanças de layout antes de publicar? | gestão | define `layout.aprovar` |
| 4 | Existem páginas que dependem de `v2_structural_portal_contents.content` para SEO/HTML específico? | conteúdo | escopo da migração manual |
| 5 | O `transaction_snapshot_id` é usado por outro sistema? | infra | decide manter ou remover a coluna |
| 6 | Os assets CSS/JS enviados precisam ser preservados? | marketing | define migração para Vite |
| 7 | O token de preview é compartilhado entre operadores? | suporte | define se preview pode ser por sessão |
| 8 | Há requisito de "desfazer" uma publicação? | produto | define versionamento de layout |

---

## 9. Checklist de aceite

- [x] `00-RESUMO.md` autossuficiente.
- [x] Toda afirmação relevante tem `arquivo:linha`.
- [x] Todo caminho citado existe no repositório.
- [x] O mapa entre versões está presente (módulo V2-only).
- [x] Bugs críticos têm caso de regressão proposto em `07-TESTES.md`.
- [x] A migração moderna é escrevível sem abrir o legado.
- [x] Nenhum arquivo de `lotep/` foi alterado.
