---
id: DATA-SEEDS-SLE
tipo: dados
onda: 5
status: concluido
unidades: [DATA-SEEDS-SLE]
fontes:
  - V2/Seeds/StructuralPortalSeeder.php
  - V2/Seeds/SleAssetSeeder.php
  - V2/Seeds/SleHeaderSeeder.php
  - V2/Seeds/SleFooterSeeder.php
  - V2/Seeds/SleConfigsSeeder.php
depende_de: [CORE-DATA, SVC-GALLERY, SVC-STORAGE, MOD-SUPPORT-STRUCTURALLANDINGEDITOR, MOD-SUPPORT-SUPPORTCONFIGS, DATA-SEEDS-BASICPAGES]
consumidores: [MOD-SUPPORT-STRUCTURALLANDINGEDITOR, MOD-LAYOUTS-HOMEPAGE, UI-PORTAL]
criticidade: alta
dono: agente-dados-iniciais
---

# SLE, assets e estrutura do portal

## 0. Ficha de identidade

| Campo | Valor |
|---|---|
| Efeito primário | Substitui o layout governamental padrão do portal por header, footer, CSS e JS da SUCESU e publica as logos e o CSS/JS do tema na File Library. |
| Entrada | `php artisan db:seed --class=StructuralPortalSeeder` (ou `db:seed`), com `v2_portal_configs.titulo_site = 'SUCESU Nacional'`. |
| Saída | 8 linhas em `v2_structural_portal_contents` (4 ativas), 3 mídias + 3 assets de imagem + 16 assets de CSS/JS em `v2_sle_assets`, arquivos em `assets/structuralEditor/{css,js}/` e em `gallery/sle/`. |
| Efeitos colaterais | Cópia de 16 arquivos CSS/JS para o disco de mídia; geração de variantes WebP para 3 PNGs; `Log::warning` quando não há variante; nenhum cache é invalidado por estes seeders. |
| Particularidade central | O seeder é **condicional ao título do site**: sem `titulo_site` exatamente igual a `SUCESU Nacional`, ele grava apenas as 8 áreas vazias e retorna. |
| Como se integra | `StructuralPortalSeeder` instancia `SleAssetSeeder`/`SleHeaderSeeder`/`SleFooterSeeder`/`SleConfigsSeeder` e passa o array de assets para header e footer. |
| Se removido, quebra | O portal volta ao layout gov padrão (header/footer vazios); o editor estrutural abre sem conteúdo; as logos do tema não aparecem. |
| Superfície pública | Classes `StructuralPortalSeeder`, `SleAssetSeeder`, `SleHeaderSeeder`, `SleFooterSeeder`, `SleConfigsSeeder`; tabelas `v2_structural_portal_contents`, `v2_sle_assets`, `v2_gallery_media`. |

## 1. Efeito

### 1.1 O que muda no portal

| Área em `v2_structural_portal_contents` | Depois do seed completo | Conteúdo | Efeito |
|---|---|---|---|
| `header` | `active=true`, `content_type='htmlmixed'` | Barra superior (saudação + data + Associe-se/Fale conosco/horário), nav principal com `$headerLinks`, telefone, redes sociais, offcanvas mobile e overlay de busca | Chrome superior SUCESU em todas as páginas que usam o layout SLE |
| `footer` | `active=true`, `content_type='htmlmixed'` | CTA "Seja um associado", colunas de `$footerLinks`, logo, telefone, endereço, copyright | Rodapé SUCESU |
| `css_head` | `active=true`, `content_type='css'` | Fontes DM Sans/Manrope, 7 CSS do tema, bridge de variáveis e overrides `!important` | Tipografia, cores e correções de Bootstrap no `<head>` |
| `js_foot` | `active=true`, `content_type='javascript'` | 9 scripts `defer` + `new WOW().init()` | Swiper, menu, contadores, animações |
| `main_left` | `active=false`, conteúdo vazio | — | Fallback gov |
| `main_right` | `active=false`, conteúdo vazio | — | Fallback gov |
| `css_foot` | `active=false`, `content_type='css'` | — | Fallback gov |
| `js_head` | `active=false`, `content_type='javascript'` | — | Fallback gov |

As 8 linhas são criadas primeiro vazias e inativas, e só então sobrescritas (`V2/Seeds/StructuralPortalSeeder.php:31-54`; `V2/Seeds/SleConfigsSeeder.php:205-224`). O `BlockRenderer` trata área vazia/inativa como ausência e renderiza o layout governamental padrão — comportamento descrito no próprio comentário do orquestrador (`V2/Seeds/StructuralPortalSeeder.php:27-29`).

### 1.2 Chaves de configuração gravadas

| Chave | Default anterior | Valor semeado | Efeito no portal | Fonte |
|---|---|---|---|---|
| `titulo_site` | `null` (migração) | `SUCESU Nacional` | Título do site, logo `alt` e **gate** do SLE | `V2/Seeds/BasicPages/SucesuHomepageSeeder.php:34`; `V2/Modules/Support/SupportConfigs/Migrations/2026_06_30_000005_create_v2_portal_configs_table.php:71` |
| `descricao` | `null` | `Sociedade de Usuários de Informática e Telecomunicações. Conectando lideranças, impulsionando o futuro da tecnologia.` | Meta description global | `V2/Seeds/BasicPages/SucesuHomepageSeeder.php:35` |
| `theme_primary_color` | `#1075ad` | `#1a3c6e` | `--tenant-primary`; header, CTAs, títulos e links | `V2/Seeds/BasicPages/SucesuHomepageSeeder.php:36`; `V2/layouts/portal/base-struct/colors.blade.php:3-14` |
| `theme_accent_color` | `#fece50` | `#f7941d` | `--tenant-accent`; hover de links e ícones | `V2/Seeds/BasicPages/SucesuHomepageSeeder.php:37`; `V2/layouts/portal/base-struct/colors.blade.php:15` |
| `theme_link_color` | `#1075ad` | `#1a3c6e` | `--tenant-links` | `V2/Seeds/BasicPages/SucesuHomepageSeeder.php:38` |
| `accessibility_bar_enabled` | ausente (CMS assume `'0'`) | `1` | Liga a barra de acessibilidade eMAG | `V2/Seeds/BasicPages/SucesuHomepageSeeder.php:39`; `V2/Modules/Support/StructuralLandingEditor/Controllers/SleCmsController.php:284-292` |
| `accessibility_widget_enabled` | ausente (`'0'`) | `1` | Liga o widget flutuante de acessibilidade | `V2/Seeds/BasicPages/SucesuHomepageSeeder.php:40` |
| `vlibras_enabled` | ausente (`'0'`) | `1` | Liga o VLibras (Libras) | `V2/Seeds/BasicPages/SucesuHomepageSeeder.php:41` |

`theme_secondary_color` **não** é semeado e permanece no default `#0a4c8c` (`V2/Modules/Support/SupportConfigs/Services/PortalConfigsService.php:202-207`); é ele que pinta a barra superior e o rodapé inferior via bridge `--theme-2`/`--header` (`V2/Seeds/SleConfigsSeeder.php:63-66`). O bridge é necessário porque o CSS do tema usa `--theme`, `--header`, `--theme-2` e `--theme-3`, enquanto o portal publica `--tenant-*` (`V2/Seeds/SleConfigsSeeder.php:60-70`).

### 1.3 Payloads de layout que o header/footer leem

| Chave em `v2_layout_base_configs` | Conteúdo | Consumo |
|---|---|---|
| `logos` | `logo_header{path,variants}`, `logo_header_alt`, `logo_footer{path,variants}`, `logo_footer_alt`, `favicon` | Header usa `logo_header`; footer usa `logo_footer`; favicon no layout | 
| `links_header` | 8 itens: Home, Sobre nós, História, Associados, Parceiros Institucionais, Convênios, Agenda, Notícias | Nav desktop e offcanvas mobile |
| `links_footer` | 4 colunas: Navegação (5), Programas (4), Institucional (4), Redes Sociais (4) | Colunas do rodapé; a coluna "Redes Sociais" troca o título por ícone |
| `contato` | `endereco`, `map_link`, `telefone_1`, `telefone_2`, `email`, `horario` | Header usa `telefone_1`; footer **não** usa o payload para endereço |
| `social_media` | 5 redes ativas (Instagram, Facebook, X, YouTube, LinkedIn) | Ícones do header |
| `landing_sections` | 8 seções `sucesu-*` | Homepage (fora do SLE) |

Fonte dos payloads: `V2/Seeds/BasicPages/SucesuHomepageSeeder.php:72-139`. O header só exibe logo visível se `$layoutConfigs->has('logos')` (`V2/Seeds/SleHeaderSeeder.php:72-83`); sem a homepage, o logo principal fica ausente e sobra apenas o fallback `logo2` em um `<a class="header-logo-2 d-none">` (`V2/Seeds/SleHeaderSeeder.php:95-105`). O footer tem fallback real para `logo4` (`V2/Seeds/SleFooterSeeder.php:115-150`).

### 1.4 O que NÃO acontece

- **Não** grava nada se `titulo_site !== 'SUCESU Nacional'`: nesse caso apenas as 8 áreas gov são gravadas e o método retorna (`V2/Seeds/StructuralPortalSeeder.php:60-67`).
- **Não** valida se o CSS/JS existe antes de gerar o payload: `css_head`/`js_foot` referenciam caminhos fixos em `public/assets/sucesu/...` (`V2/Seeds/SleConfigsSeeder.php:46-58,167-175`). Se o tema não estiver publicado, o HTML aponta para 404.
- **Não** abre transação em nenhum dos cinco seeders; cada `updateOrInsert`/`create` autocommita.
- **Não** remove assets antigos: `SleAssetSeeder` só insere (`V2/Modules/Support/StructuralLandingEditor/Services/AssetManagerService.php:42-49`).
- **Não** limpa cache de página, view ou opcache. O `SleCmsController` faz isso em requisições do CMS, não o seeder.
- **Não** usa o payload `contato` no endereço do footer: o texto é literal no Blade (`V2/Seeds/SleFooterSeeder.php:163-171`).

## 2. Abordagem

### 2.1 Estratégia

O orquestrador prepara o terreno com o fallback gov, checa o "produto" configurado (`titulo_site`) e delega a quatro seeders independentes. O estado final é sempre uma substituição integral das áreas, não um merge: o conteúdo anterior do editor estrutural é perdido.

```mermaid
flowchart TD
  A[StructuralPortalSeeder] --> B[8 áreas gov: conteúdo vazio, active=false]
  B --> C{titulo_site === 'SUCESU Nacional'?}
  C -- não --> Z[retorna: portal gov]
  C -- sim --> D[SleAssetSeeder: 3 imagens + 7 CSS + 9 JS]
  D --> E[SleHeaderSeeder assets]
  E --> F[SleFooterSeeder assets]
  F --> G[SleConfigsSeeder: css_head, js_foot, 4 áreas vazias]
  G --> H[portal SUCESU: 4 áreas ativas]
```

### 2.2 Ordem e dependências

| # | Etapa | Depende de | Consequência se fora de ordem |
|---|---|---|---|
| 1 | 8 áreas gov vazias | tabela migrada | Sem elas, `updateOrInsert` criaria as linhas depois; não é crítico, mas o fallback intermediário não existe. |
| 2 | Gate `titulo_site` | `SucesuHomepageSeeder` | Rodar `StructuralPortalSeeder` isolado em base nova cai em "Modo gov detectado" (`V2/Seeds/StructuralPortalSeeder.php:64-66`). |
| 3 | `SleAssetSeeder` | `public/assets/sucesu/**` | Header/footer recebem `null` e caem nos fallbacks; nenhuma exceção sobe. |
| 4 | `SleHeaderSeeder` | assets + payloads `logos`/`links_header`/`contato`/`social_media` | Sem payloads, nav/telefone/redes vazios; logo principal ausente. |
| 5 | `SleFooterSeeder` | assets + `links_footer` | Sem payload, nenhuma coluna de links; CTA e endereço continuam. |
| 6 | `SleConfigsSeeder` | nenhuma (payload estático) | Pode rodar antes; o `updateOrInsert` é o mesmo. |

O comentário do orquestrador afirma que os sub-seeders "usam updateOrInsert, substituindo os registros gov existentes" (`V2/Seeds/StructuralPortalSeeder.php:71`), o que é verdade para áreas, mas não para `v2_sle_assets`, que sempre insere.

### 2.3 Mecânica passo a passo

1. `StructuralPortalSeeder::run()` calcula `$now` e percorre as 8 áreas, escolhendo `content_type` por área: `css` para `css_head`/`css_foot`, `javascript` para `js_head`/`js_foot`, `htmlmixed` para o resto (`V2/Seeds/StructuralPortalSeeder.php:31-39`).
2. Cada área é gravada com `updateOrInsert(['area' => ...])`, `content=''`, `active=false` e o `id` existente preservado (`V2/Seeds/StructuralPortalSeeder.php:41-51`).
3. Lê `titulo_site` com `DB::table(...)->value()` e compara com string exata; diferente → retorna (`V2/Seeds/StructuralPortalSeeder.php:60-67`).
4. `SleAssetSeeder::run()` envia `logo2.png`, `logo4.png` e `footer/bg-1.png` para `GalleryService::seedFromPath()` e registra cada uma em `v2_sle_assets` via `createFromGallery()` (`V2/Seeds/SleAssetSeeder.php:44-74`).
5. Em seguida, percorre 7 CSS e 9 JS de `public/assets/sucesu/`, copiando cada um para `assets/structuralEditor/{css,js}/<nome>` e criando um `SleAsset` com snippet (`V2/Seeds/SleAssetSeeder.php:82-115`; `V2/Modules/Support/StructuralLandingEditor/Services/AssetManagerService.php:26-51`).
6. `SleHeaderSeeder::run($assets)` extrai `file_path`, `variants` e `disk` de `logo2`, monta o Blade do header em heredoc e grava a área `header` com `active=true` (`V2/Seeds/SleHeaderSeeder.php:28-35,196-206`).
7. `SleFooterSeeder::run($assets)` faz o mesmo com `logo4` e `footerBg` e grava a área `footer` (`V2/Seeds/SleFooterSeeder.php:28-36,191-201`).
8. `SleConfigsSeeder::run()` grava `css_head` e `js_foot` ativos e reafirma as 4 áreas vazias inativas (`V2/Seeds/SleConfigsSeeder.php:182-224`).
9. `SleAssetSeeder` captura qualquer exceção do bloco e apenas loga `Erro no SleAssetSeeder: ...`, retornando o que conseguiu processar (`V2/Seeds/SleAssetSeeder.php:117-121`).

### 2.4 Trechos de código pivô

```php
// V2/Seeds/StructuralPortalSeeder.php:33-52 — estado inicial gov
foreach ($govAreas as $area) {
    $defaultType = 'htmlmixed';
    if (in_array($area, ['css_head', 'css_foot'])) {
        $defaultType = 'css';
    } elseif (in_array($area, ['js_head', 'js_foot'])) {
        $defaultType = 'javascript';
    }

    DB::table('v2_structural_portal_contents')->updateOrInsert(
        ['area' => $area],
        [
            'id'           => DB::table('v2_structural_portal_contents')->where('area', $area)->value('id') ?? v2_uuid(),
            'content'      => '',
            'content_type' => $defaultType,
            'active'       => false,
            'created_at'   => $now,
            'updated_at'   => $now,
        ]
    );
}
```

As 8 áreas existem sempre; o que muda é `active` e `content`. Note que `created_at` é reescrito em toda execução, inclusive quando a linha já existia.

```php
// V2/Seeds/StructuralPortalSeeder.php:60-67 — gate por string exata
$siteTitle = DB::table('v2_portal_configs')
    ->where('config_key', 'titulo_site')
    ->value('config_value');

if ($siteTitle !== 'SUCESU Nacional') {
    $this->command->info('Modo gov detectado. Nenhum conteúdo SLE adicional necessário.');
    return;
}
```

Espaço, caixa ou acento diferente desligam todo o conteúdo SLE. Como `SucesuHomepageSeeder` grava exatamente esse valor, a ordem do `DatabaseSeeder` é um contrato.

```php
// V2/Seeds/StructuralPortalSeeder.php:76-95 — assets alimentam header e footer
$assetSeeder = new SleAssetSeeder();
$assetSeeder->setContainer(app());
$assetSeeder->setCommand($this->command);
$assets = $assetSeeder->run();

// ── 2b.  Header ─────────────────────────────────────────────────────
$this->command->info('');
$this->command->info('═══ 2/4  Header ═══');
$headerSeeder = new SleHeaderSeeder();
$headerSeeder->setContainer(app());
$headerSeeder->setCommand($this->command);
$headerSeeder->run($assets);

// ── 2c.  Footer ─────────────────────────────────────────────────────
$this->command->info('');
$this->command->info('═══ 3/4  Footer ═══');
$footerSeeder = new SleFooterSeeder();
$footerSeeder->setContainer(app());
$footerSeeder->setCommand($this->command);
$footerSeeder->run($assets);
```

O array de assets é o único acoplamento entre os sub-seeders; `null` em uma chave vira string vazia no Blade.

```php
// V2/Seeds/SleAssetSeeder.php:44-60 — 3 imagens por execução, sem deduplicação
$images = [
    'logo2'      => ['path' => 'assets/sucesu/img/logo2.png',      'alt' => 'Logo secundário SUCESU - Header'],
    'logo4'      => ['path' => 'assets/sucesu/img/logo4.png',      'alt' => 'Logo fallback SUCESU - Footer'],
    'footerBg'   => ['path' => 'assets/sucesu/img/footer/bg-1.png','alt' => 'Background do footer SUCESU'],
];

foreach ($images as $key => $info) {
    $fullPath = public_path($info['path']);
    if (!file_exists($fullPath)) {
        $this->command->warn("  ✗ Arquivo não encontrado: {$info['path']}");
        $result[$key] = null;
        continue;
    }

    // seedFromPath() → UploadedFile test → MediaInputer → ImageOptimizer → WebP variants
    $media = $gallery->seedFromPath($fullPath, $galleryConfig, $key, $info['alt']);
    $result[$key] = $media;
```

`seedFromPath()` usa `logo2`/`logo4`/`footerBg` como nome fixo e grava em `gallery/sle/<key>.<ext>`; o arquivo é sobrescrito, mas `v2_gallery_media` ganha nova linha a cada run.

```php
// V2/Modules/Support/StructuralLandingEditor/Services/AssetManagerService.php:31-49 — CSS/JS sempre viram novo asset
$subdir = $type === 'css' ? 'css' : 'js';
$filename = $customFilename
    ? $customFilename . '.' . $extension
    : uniqid('vendor_') . '_' . time() . '.' . $extension;
$storagePath = 'assets/structuralEditor/' . $subdir . '/' . $filename;

$contents = file_get_contents($file->getRealPath());
$this->storageService->put($contents, $storagePath, ['visibility' => 'public']);

$snippet = $this->generateVendorSnippet($type, $storagePath);

$asset = SleAsset::create([
    'type'          => $type,
    'original_name' => $originalName,
    'storage_path'  => $storagePath,
    'mime_type'     => $file->getMimeType(),
    'file_size'     => $file->getSize(),
    'snippet'       => $snippet,
]);
```

Não há consulta por `storage_path`/`original_name` antes do `create`: 16 novas linhas em `v2_sle_assets` por execução, enquanto o arquivo físico é substituído no mesmo caminho.

```php
// V2/Seeds/SleHeaderSeeder.php:196-206 — substituição integral do header
DB::table('v2_structural_portal_contents')->updateOrInsert(
    ['area' => 'header'],
    [
        'id'           => DB::table('v2_structural_portal_contents')->where('area', 'header')->value('id') ?? v2_uuid(),
        'content'      => $headerBlade,
        'content_type' => 'htmlmixed',
        'active'       => true,
        'created_at'   => $now,
        'updated_at'   => $now,
    ]
);
```

O Blade inteiro é regravado; customizações feitas no editor estrutural (CMS) são perdidas. O footer segue o mesmo padrão (`V2/Seeds/SleFooterSeeder.php:191-201`).

```php
// V2/Seeds/SleConfigsSeeder.php:60-70 — bridge entre o CSS legado e as tenant vars
{{-- Bridge: mapeia variáveis legadas SUCESU → tenant vars do PortalConfigsService --}}
<style>
    :root {
        --theme: var(--tenant-primary);
        --header: var(--tenant-primary);
        --theme-2: var(--tenant-secondary);
        --theme-3: var(--tenant-accent);
        --ratting: var(--tenant-accent);
        --white: var(--color-bg-main);
        --bg: var(--color-bg-canvas);
    }
```

O CSS do tema continua usando nomes legados; sem esse bloco, trocar `theme_primary_color` no CMS não mudaria header/CTAs. O restante do payload força `body`/headings com `var(--font-sans)` e reescreve `.btn-primary`/`.bg-primary`/`.text-primary` (`V2/Seeds/SleConfigsSeeder.php:72-108`).

```php
// V2/Seeds/SleConfigsSeeder.php:187-200 — css_head/js_foot com active=true
foreach ($areas as $item) {
    DB::table('v2_structural_portal_contents')->updateOrInsert(
        ['area' => $item['area']],
        [
            'id'           => DB::table('v2_structural_portal_contents')->where('area', $item['area'])->value('id') ?? v2_uuid(),
            'content'      => $item['content'],
            'content_type' => $item['type'],
            'active'       => true,
            'created_at'   => $now,
            'updated_at'   => $now,
        ]
    );
    $this->command->info("✓ {$item['area']} → conteúdo salvo");
}
```

`created_at` volta para o instante do seed em toda reexecução, distorcendo a auditoria da linha; o mesmo ocorre com header e footer.

### 2.5 Custos e limites

- 3 uploads de imagem (com WebP 360/720/1200/1920) + 16 cópias de CSS/JS + 16 `INSERT`s em `v2_sle_assets` por execução.
- Header e footer renderizam `@include('v2-service-media::components.picture')` no runtime; o seeder só injeta os caminhos/variantes, não renderiza HTML de imagem.
- Não há transação: uma falha entre header e footer deixa o portal com um dos dois lados gov.
- `SleAssetSeeder` não propaga erro; `SleHeaderSeeder`/`SleFooterSeeder`/`SleConfigsSeeder` podem falhar e abortar o restante.

## 3. Particularidades

### 3.1 Idempotência comprovada

| Seeder | Mecanismo | Prova | Resultado |
|---|---|---|---|
| `StructuralPortalSeeder` (áreas) | `updateOrInsert(['area' => ...])` | `V2/Seeds/StructuralPortalSeeder.php:41-51` | Não duplica; conteúdo é zerado e `active=false`. |
| `SleAssetSeeder` (imagens) | `GalleryService::upload()` sem consulta prévia | `V2/Services/Gallery/Services/GalleryService.php:65-75` | Novas mídias a cada run. |
| `SleAssetSeeder` (CSS/JS) | `SleAsset::create()` sem consulta prévia | `V2/Modules/Support/StructuralLandingEditor/Services/AssetManagerService.php:42-49` | Novos assets a cada run. |
| `SleHeaderSeeder` | `updateOrInsert(['area' => 'header'])` | `V2/Seeds/SleHeaderSeeder.php:196-206` | Uma linha; conteúdo substituído. |
| `SleFooterSeeder` | `updateOrInsert(['area' => 'footer'])` | `V2/Seeds/SleFooterSeeder.php:191-201` | Uma linha; conteúdo substituído. |
| `SleConfigsSeeder` | `updateOrInsert` por área | `V2/Seeds/SleConfigsSeeder.php:188-198,214-224` | Não duplica; conteúdo substituído. |
| `v2_sle_assets` (imagens) | `createFromGallery` deduplica por `gallery_media_id` | `V2/Modules/Support/StructuralLandingEditor/Services/AssetManagerService.php:102-122` | Não duplica **na mesma** mídia; como a mídia é nova, o asset também é. |

### 3.2 Escritas que sobrescrevem conteúdo editado

| Alvo | O que é perdido |
|---|---|
| `v2_structural_portal_contents.header` | Todo o markup editado no editor estrutural; volta ao Blade do seeder. |
| `v2_structural_portal_contents.footer` | Idem. |
| `v2_structural_portal_contents.css_head` / `js_foot` | CSS/JS customizados; voltam ao payload fixo. |
| `v2_structural_portal_contents.main_left` / `main_right` / `css_foot` / `js_head` | Qualquer conteúdo é zerado e a área é desativada (`V2/Seeds/SleConfigsSeeder.php:205-224`). |
| `created_at` das 4 áreas ativas | Reescrito para `now()`. |

Não há `delete`/`truncate` nesta unidade; a limpeza é por sobrescrita.

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

| ID | Regra | Efeito | Fonte |
|---|---|---|---|
| `RN-DATA-SEEDS-SLE-01` | O SLE só ativa com `titulo_site === 'SUCESU Nacional'`. | Qualquer outro valor mantém o portal gov. | `V2/Seeds/StructuralPortalSeeder.php:60-67` |
| `RN-DATA-SEEDS-SLE-02` | As áreas são gravadas vazias antes de serem preenchidas. | Falha no meio deixa header/footer gov, não o conteúdo antigo. | `V2/Seeds/StructuralPortalSeeder.php:31-54` |
| `RN-DATA-SEEDS-SLE-03` | Header e footer recebem assets por parâmetro; não consultam a Galeria. | Sem `SleAssetSeeder`, os caminhos ficam vazios. | `V2/Seeds/SleHeaderSeeder.php:28-35`; `V2/Seeds/SleFooterSeeder.php:28-36` |
| `RN-DATA-SEEDS-SLE-04` | `logo_header` vem do payload `logos`, não de `v2_sle_assets`. | Sem homepage, o logo visível do header não aparece. | `V2/Seeds/SleHeaderSeeder.php:72-105` |
| `RN-DATA-SEEDS-SLE-05` | O endereço do footer é literal, não vem de `contato`. | Editar `contato.endereco` no CMS não altera o rodapé. | `V2/Seeds/SleFooterSeeder.php:163-171` |
| `RN-DATA-SEEDS-SLE-06` | 16 assets de CSS/JS são inseridos por execução, com o mesmo `storage_path`. | A File Library cresce e o arquivo físico é sobrescrito. | `V2/Modules/Support/StructuralLandingEditor/Services/AssetManagerService.php:31-49` |

### 3.4 Casos-limite e armadilhas

- **Gate sensível a string:** `titulo_site` com espaço no fim, `SUCESU NACIONAL` ou `Sucesu Nacional` cai no modo gov. O valor é gravado pela homepage (`V2/Seeds/BasicPages/SucesuHomepageSeeder.php:34`), mas pode ser editado no CMS.
- **`SleAssetSeeder` engole exceções:** falha de Storage/Gallery não impede header/footer, que ficam com `originalPath=''`; o portal renderiza `<picture>` vazio ou quebrado.
- **CSS/JS ausentes:** `SleAssetSeeder` pula arquivo inexistente com `continue` (`V2/Seeds/SleAssetSeeder.php:90-96,110-116`), mas `SleConfigsSeeder` referencia os 16 caminhos de qualquer forma.
- **Imagens SVG:** o CSS/JS não passa por WebP; as 3 imagens SLE são PNG e geram variantes. Já os ícones das BasicPages são SVG e não geram variantes — o warning do `SleAssetSeeder` não aparece para eles, pois ele só processa os 3 PNGs.
- **`variantsForBlade`:** converte o JSON de variantes em array PHP literal e o injeta no heredoc (`V2/Seeds/SleHeaderSeeder.php:217-228`); variantes com aspas simples são escapadas por `var_export`, mas qualquer mudança no formato do JSON quebra a sintaxe do Blade gerado.
- **Header com data em inglês:** `date('F')` sem localização produz `October`, `November` etc. (`V2/Seeds/SleHeaderSeeder.php:48-55`).
- **Telefone divergente:** header usa `contato.telefone_1` com fallback `(81) 99602-4167`; o footer tem o mesmo fallback, mas o endereço é fixo (`V2/Seeds/SleHeaderSeeder.php:127-134`; `V2/Seeds/SleFooterSeeder.php:153-171`).
- **Menu duplicado no mobile:** o offcanvas repete `headerLinks` e adiciona um item fixo "Início" (`V2/Seeds/SleHeaderSeeder.php:166-177`); se `links_header` já tiver Home, o item aparece duas vezes.
- **Busca depende de rota:** o overlay usa `route('v2.portal.search')`; se a rota não existir, o seeder gera Blade que lança erro em runtime (`V2/Seeds/SleHeaderSeeder.php:185-188`).
- **`active=false` em `main_left`/`main_right`:** o editor estrutural pode mostrar as áreas, mas o portal usa o fallback gov.

### 3.5 Divergências e dívidas

- O docblock do `SleAssetSeeder` promete "3 imagens, 7 CSS e 9 JS" (`V2/Seeds/SleAssetSeeder.php:12-22`), mas os assets de imagem são registrados duas vezes: primeiro via `GalleryService`, depois via `createFromGallery` (`V2/Seeds/SleAssetSeeder.php:59,73`). Isso é intencional (galeria + File Library), porém duplica o custo.
- `SleConfigsSeeder` grava `created_at` no `updateOrInsert` (`V2/Seeds/SleConfigsSeeder.php:195`), o que faz a linha parecer recém-criada em toda execução.
- `SleHeaderSeeder` e `SleFooterSeeder` têm `variantsForBlade()` duplicado, com o mesmo corpo (`V2/Seeds/SleHeaderSeeder.php:217-228`; `V2/Seeds/SleFooterSeeder.php:212-223`).
- O CSS head injeta `assets/vendor/dm-sans/fonts.css` e `assets/vendor/manrope/fonts.css` (`V2/Seeds/SleConfigsSeeder.php:38-42`), caminhos que não são validados pelo seeder e dependem do build do tema.
- O rodapé usa `date('Y')` no copyright (`V2/Seeds/SleFooterSeeder.php:183`): o ano não é fixado no seed, é resolvido a cada renderização do Blade armazenado.

## 4. Integrabilidade

### 4.1 Superfície pública

| Símbolo | Tipo | Assinatura | Precondição | Consumidores |
|---|---|---|---|---|
| `StructuralPortalSeeder::run()` | público | `run(): void` | `v2_portal_configs` e `v2_structural_portal_contents` migradas | `DatabaseSeeder`, artisan |
| `SleAssetSeeder::run()` | público | `run(): array` | arquivos em `public/assets/sucesu/**` | `StructuralPortalSeeder` |
| `SleHeaderSeeder::run()` | público | `run($assets = null): void` | array de assets (pode ser `null`) | `StructuralPortalSeeder` |
| `SleFooterSeeder::run()` | público | `run($assets = null): void` | array de assets (pode ser `null`) | `StructuralPortalSeeder` |
| `SleConfigsSeeder::run()` | público | `run(): void` | tabela de áreas | `StructuralPortalSeeder` |
| `variantsForBlade()` | privado | `variantsForBlade($variantsJson): string` | JSON válido ou `'[]'` | Uso interno |

### 4.2 Receitas de uso

```bash
# 1. Fluxo completo (respeita o gate)
php artisan db:seed --class=V2\\Seeds\\BasicPages\\SucesuHomepageSeeder
php artisan db:seed --class=StructuralPortalSeeder
```

```bash
# 2. Apenas reaplicar o chrome SUCESU (base já com titulo_site correto)
php artisan db:seed --class=StructuralPortalSeeder
# Resultado: header/footer/css_head/js_foot regravados; 19 novos assets em v2_sle_assets.
```

```php
// 3. Atualizar só uma área (ex.: footer) sem tocar nas demais
Artisan::call('db:seed', ['--class' => \V2\Seeds\SleFooterSeeder::class]);
// Sem $assets, logo4/footerBg viram string vazia; o footer ainda é gravado.
```

```php
// 4. Ler o conteúdo efetivo do portal
DB::table('v2_structural_portal_contents')
    ->where('active', true)
    ->pluck('area'); // ['css_head','footer','header','js_foot']
```

### 4.3 Anti-uso

- **Rodar `StructuralPortalSeeder` antes da homepage.** O gate falha e o portal fica gov; nenhum aviso além de "Modo gov detectado" (`V2/Seeds/StructuralPortalSeeder.php:64-66`).
- **Editar header/footer no CMS e rodar o seeder.** O Blade é substituído integralmente (`V2/Seeds/SleHeaderSeeder.php:196-206`).
- **Chamar `SleFooterSeeder` isolado esperando as logos.** Sem `$assets`, `logo4Path`/`footerBgPath` são `''`; o footer é gravado com imagem vazia.
- **Desativar `header` no CMS para usar o gov.** O próximo `db:seed` reativa (`active=true`).
- **Contar com o CSS/JS antigo na File Library.** Cada run adiciona 16 novos assets; o editor mostra duplicatas com o mesmo nome.

### 4.4 Consumidores e risco

- `MOD-SUPPORT-STRUCTURALLANDINGEDITOR`: lê e edita as 8 áreas; um seed apaga o trabalho editorial.
- `UI-PORTAL`: o layout base injeta `css_head`/`js_foot` e renderiza `header`/`footer`; caminhos quebrados afetam todas as páginas.
- `MOD-SUPPORT-SUPPORTCONFIGS`: `theme_*`, `titulo_site` e flags de acessibilidade são lidos pelo `PortalConfigsService` e injetados em `--tenant-*`.
- `SVC-STORAGE` / `SVC-GALLERY`: são a infraestrutura dos uploads; indisponibilidade leva a assets vazios, não a erro fatal.
- `MOD-LAYOUTS-HOMEPAGE`: usa `landing_sections`; não depende diretamente destes seeders, mas o header/footer da homepage depende do SLE.

## 5. Lacunas

- `LG-DATA-SEEDS-SLE-01`: não foi localizado o ponto exato em que `BlockRenderer` decide "área vazia → layout gov"; o comportamento é afirmado no comentário do seeder e nos testes de fumaça, não lido nesta unidade. Onde procurar: `MOD-SUPPORT-STRUCTURALLANDINGEDITOR`.
- `LG-DATA-SEEDS-SLE-02`: não há teste que valide o gate `titulo_site` nem a ausência de transação; a análise é estática. Onde procurar: `tests/Feature/V2/`.
- `LG-DATA-SEEDS-SLE-03`: não foi possível confirmar se `PublicCacheMiddleware` invalida o cache depois de uma alteração direta em `v2_structural_portal_contents`; o seeder não invalida nada. Onde procurar: `CORE-RUNTIME` e comandos de cache.
- `LG-DATA-SEEDS-SLE-04`: o efeito visual exato do CSS head depende do build de `public/assets/sucesu/css/main.min.css`, que não foi analisado aqui.

## 6. Evidências

| Arquivo | Faixas lidas |
|---|---|
| `V2/Seeds/StructuralPortalSeeder.php` | 1-108 |
| `V2/Seeds/SleAssetSeeder.php` | 1-123 |
| `V2/Seeds/SleHeaderSeeder.php` | 1-229 |
| `V2/Seeds/SleFooterSeeder.php` | 1-224 |
| `V2/Seeds/SleConfigsSeeder.php` | 1-229 |
| `V2/Seeds/BasicPages/SucesuHomepageSeeder.php` | 33-139 |
| `V2/Modules/Support/StructuralLandingEditor/Services/AssetManagerService.php` | 26-120 |
| `V2/Modules/Support/StructuralLandingEditor/Migrations/2026_07_03_000000_create_v2_structural_portal_blocks_table.php` | 18-30 |
| `V2/Modules/Support/StructuralLandingEditor/Migrations/2026_07_06_000000_create_v2_sle_assets_table.php` | 18-38 |
| `V2/Modules/Support/SupportConfigs/Migrations/2026_06_30_000005_create_v2_portal_configs_table.php` | 36-120 |
| `V2/Modules/Support/SupportConfigs/Services/PortalConfigsService.php` | 190-245 |
| `V2/layouts/portal/base-struct/colors.blade.php` | 1-35 |
| `V2/Services/Gallery/Services/GalleryService.php` | 53-90 |
