---
id: MOD-SUPPORT-SUPPORTCONFIGS-CMS
tipo: modulo
onda: 3
status: concluido
unidades: [MOD-SUPPORT-SUPPORTCONFIGS]
fontes:
  - V2/Modules/Support/SupportConfigs/
depende_de: [UI-CMS, CORE-CMS]
consumidores: [MOD-SUPPORT-STRUCTURALLANDINGEDITOR]
criticidade: alta
dono: PageSupportConfigs
---

# Support/SupportConfigs — UI CMS

> Anexo do módulo `spec.md`. Descreve a única tela do módulo: um painel de quatro abas
> (Módulos, Sistema & Manutenção, Suporte de Usuários, Logs) com sidebar própria,
> diagnóstico fixo, dois modais, três chamadas `fetch` e quatro formulários POST.
> Não há listagem paginada, filtro, bulk action nem componente reutilizável.

## 0. Ficha de identidade

| Campo | Valor |
|---|---|
| Efeito primário | Dar ao e-mail de suporte uma tela única para ver o estado do sistema e executar operações destrutivas (flag, manutenção, debug, senha, log, cache) com confirmação no navegador. |
| Entrada | `GET /cms/infra/support-configs`; interações: switches, formulários, selects, modais. |
| Saída | Quatro parciais Blade dentro de `v2-cms::layouts.app`; chamadas AJAX; redirects com flash. |
| Efeitos colaterais | `confirm()`/modais disparam POSTs imediatos; atualização visual de card sem recarregar; `reloadLogs()` a cada `shown.bs.tab` da aba Logs. |
| Particularidade central | A tela repete a checagem de e-mail no Blade e tem um branch “Acesso Negado” **inalcançável**, porque o controller aborta `403` antes de renderizar. |
| Como se integra | `v2-supportconfigs::cms.supportConfigs.index` + `tabs.{modulos,manutencao,suporte,logs}`; Bootstrap 5 (`data-bs-toggle="pill"`, `bootstrap.Modal`); `fetch`; `DOMPurify` opcional. |
| Se removido, quebra | Não há outra UI para flags/controles/logs/senha; a rota de reset do tema (SLE) continua existindo sem tela própria. |
| Superfície pública | IDs de DOM e eventos listados em §4.1; classes `.module-toggle`, `.module-card`, `.module-icon`; funções globais `reloadLogs`, `friendlyLogName`, `renderFileSummary`, `formatBytes`, `showUserDetail`, `showPasswordReset`. |

## 1. Efeito

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

- Ver, sem recarregar, o estado de cada módulo e alterná-lo com um switch; um modal explica o impacto antes de confirmar e o card muda de cor após o `200` (`modulos.blade.php:187-300`).
- Ver diagnóstico (10 linhas) e limpar cache com um clique e `confirm()` (`index.blade.php:70-104`).
- Alternar manutenção/`APP_DEBUG`/debugbar e aplicar; os três switches vão juntos no mesmo POST (`manutencao.blade.php:7-108`).
- Buscar usuário, abrir detalhes por AJAX (papéis, permissões, último login, 30 atividades) e abrir o modal de nova senha (`suporte.blade.php:9-140,144-205`).
- Selecionar um arquivo de log, recarregar o tail, navegar por cards de arquivos e limpar com confirmação (`logs.blade.php:28-92,99-284`).
- Ver os 4 alertas de flash (`success`/`error`) no topo (`index.blade.php:12-33`).

### 1.2 O que muda no sistema

| Ação de UI | Efeito | Fonte |
|---|---|---|
| Switch de módulo + confirmar | `POST modules/toggle`; `v2_module_flags` alterado; card/ícone recoloridos; `alert` em erro | `modulos.blade.php:226-300` |
| “Limpar Cache” | `POST clear-cache`; recarrega a página com flash | `index.blade.php:98-103` |
| “Aplicar Controles de Sistema” | `POST system-controls/save`; recarrega com flash | `manutencao.blade.php:7,104-107` |
| “Buscar” | `GET users/search?q=`; redirect e tabela renderizada da sessão | `suporte.blade.php:9-22,31-77` |
| Ícone de olho | `fetch users/detail/{id}`; injeta HTML em `#user-detail-content` | `suporte.blade.php:144-202` |
| “Resetar Senha” | `POST users/reset-password`; altera senha; recarrega | `suporte.blade.php:99-140` |
| Abrir aba Logs | `fetch logs/tail?lines=500`; preenche viewer e cards | `logs.blade.php:274-284` |
| “Limpar Log” | `POST logs/clear`; backup + truncamento; recarrega | `logs.blade.php:47-55` |

### 1.3 Contrato observável

| Interação | Resultado na tela |
|---|---|
| Abrir painel como suporte | 4 abas, aba Módulos ativa, diagnóstico preenchido |
| Abrir painel como não-suporte | `403` (a view não chega a renderizar) |
| Flag alterada com sucesso | switch mantém o novo estado, card perde/ganha `bg-light`, ícone muda de cor; nenhum toast |
| Flag com erro HTTP | switch volta, `alert('Erro: ' + message)` ou `alert('Erro de comunicação. Tente novamente.')` |
| Cancelar modal de flag | switch volta ao estado anterior via `hidden.bs.modal` |
| Busca com 1 caractere | form não envia (`minlength=2`); servidor também recusa |
| Busca sem resultado | alerta `Nenhum usuário encontrado para o termo "<termo>".` |
| Senha < 6 | `minlength` bloqueia no cliente; servidor repete a regra |
| Log sem arquivo | viewer mostra `[INFO] Arquivo de log não encontrado ou ainda vazio.` |
| Log vazio | `[ LOG VAZIO ]` |
| Falha de rede nos logs | bloco vermelho `Erro ao carregar logs.` |

### 1.4 O que esta UI NÃO faz

- Não edita tema do CMS, tema do portal, SEO, metadados nem SMTP: essas abas vivem na SLE; esta tela só consome `resetCmsTheme` por uma rota à parte.
- Não tem paginação, ordenação, busca ou bulk action em listagens (as duas “listagens” são cards de módulos e tabela de usuários com ≤20 linhas).
- Não tem confirmação server-side: `confirm()` e modal são apenas client-side.
- Não atualiza automaticamente: logs só recarregam ao abrir a aba, clicar em “Recarregar” ou trocar o select.
- Não exibe o grupo `SUPPORT` (filtrado) nem módulos com grupo `OUTROS`/vazio.
- Não permite escolher o número de linhas do log (fixo em 500 na UI, embora o servidor aceite 50–2000).
- Não tem rota/tela para `modules/batch`: o formulário em lote não existe.

## 2. Abordagem

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

Uma view “container” (`index.blade.php`) monta o layout, a sidebar de pills e o diagnóstico; cada aba é um `@component('v2-cms::components.box')` incluído em um `tab-pane`. O estado inicial vem do controller; o estado pós-ação vem de flash ou de `fetch`. O JS é inline, por aba, usando `@push('js')` (Módulos) ou `@push('scripts')` (Suporte, Logs), e Bootstrap 5 para tabs/modais.

```mermaid
flowchart TD
  IDX[index.blade.php] --> DIAG[card Diagnóstico + Limpar Cache]
  IDX --> T1["tab_modulos -> modulos.blade.php"]
  IDX --> T2["tab_manutencao -> manutencao.blade.php"]
  IDX --> T3["tab_suporte_user -> suporte.blade.php"]
  IDX --> T4["tab_logs -> logs.blade.php"]
  T1 -->|fetch JSON| R3[modules/toggle]
  T3 -->|form GET| R6[users/search]
  T3 -->|fetch JSON| R7[users/detail/id]
  T3 -->|form POST| R8[users/reset-password]
  T4 -->|fetch JSON| R9[logs/tail]
  T4 -->|form POST| R10[logs/clear]
  DIAG -->|form POST| R2[clear-cache]
  T2 -->|form POST| R5[system-controls/save]
```

### 2.2 Mecânica passo a passo

1. **Controller** monta `diagnostics`, `modules`, `systemControls`, `history` e devolve a view (`SupportConfigsCmsController.php:59-71`).
2. **Layout**: `@extends('v2-cms::layouts.app', ['title'=>'Configurações'])`; breadcrumbs Dashboard → Suporte → Configurações (`index.blade.php:1-8`).
3. **Guarda de view**: `@if(Sentinel::check() && Sentinel::getUser()->email === config('v2.support.email'))`; o `@else` mostra “Acesso Negado” (`:10,132-137`).
4. **Flash**: dois blocos dismissíveis (`success`, `error`) com `<h4>` e `btn-close` (`:12-33`).
5. **Sidebar**: quatro `<button class="nav-link" data-bs-toggle="pill" data-bs-target="#tab_...">` com `role="tab"`, `aria-controls`, `aria-selected` (`:38-58`).
6. **Diagnóstico**: `<dl>` com PHP, Laravel, Ambiente, Debug, Cache, Sessão, Fila, BD, Último Cron e form de limpeza (`:61-104`).
7. **Panes**: `#tab_modulos` (`active`), `#tab_manutencao`, `#tab_suporte_user`, `#tab_logs`, cada um com `role="tabpanel"` e `aria-labelledby` (`:108-129`).
8. **Rodapé**: `@include('v2-cms::partials.activity-footer', ['model'=>null,'history'=>$history ?? null])` (`:140-141`).
9. **Interações**: ver §4; todo POST carrega `csrf_field()`; todo `fetch` envia `X-CSRF-TOKEN` (só o toggle) ou depende do cookie de sessão + `Accept` (detalhe e logs são GET).

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

- **Pills em vez de tabs de topo** `[C]`: sidebar vertical fixa de 4 itens, com a aba Módulos ativa por padrão (`index.blade.php:41-57,111`).
- **Diagnóstico sempre visível** `[C]`: fica fora das panes, na coluna esquerda, para consulta durante qualquer operação (`:61-104`).
- **Modal de confirmação para flag, `confirm()` para o resto** `[C]`: só o toggle tem modal rico com texto dinâmico; cache/log/senha usam `confirm()` nativo (`modulos.blade.php:137-170`; `index.blade.php:100`; `logs.blade.php:53`; `suporte.blade.php:133`).
- **Atualização otimista do card** `[C]`: o switch mantém o estado e o card é recolorido sem recarregar; em erro, o estado é revertido (`modulos.blade.php:257-289`).
- **JS inline por aba** `[C]`: não há arquivo `.js` do módulo; cada parcial empilha seu script. Funções viram globais (`reloadLogs`, `showUserDetail`), criando acoplamento por nome.
- **HTML montado por concatenação** `[C]`: o detalhe do usuário é construído em string e injetado com `innerHTML`; os campos vêm do JSON do servidor (`suporte.blade.php:157-197`).
- **Sanitização opcional do log** `[C]`: se `DOMPurify` existir, usa `sanitize`; senão, `textContent` (perde o colorido) (`logs.blade.php:180-184`).
- **URL hardcoded no detalhe** `[C]`: `/cms/infra/support-configs/users/detail/` em vez de `route()` (`suporte.blade.php:150`).

### 2.4 Trechos de código pivô

```blade
{{-- V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/index.blade.php:108-129 — panes e inclusão das abas. --}}
<div class="tab-content" id="support-tabs-content">
    <div class="tab-pane fade show active" id="tab_modulos" role="tabpanel" aria-labelledby="tab-modulos-tab">
        @include('v2-supportconfigs::cms.supportConfigs.tabs.modulos')
    </div>
    <div class="tab-pane fade" id="tab_manutencao" role="tabpanel" aria-labelledby="tab-manutencao-tab">
        @include('v2-supportconfigs::cms.supportConfigs.tabs.manutencao')
    </div>
    <div class="tab-pane fade" id="tab_suporte_user" role="tabpanel" aria-labelledby="tab-suporte-tab">
        @include('v2-supportconfigs::cms.supportConfigs.tabs.suporte')
    </div>
    <div class="tab-pane fade" id="tab_logs" role="tabpanel" aria-labelledby="tab-logs-tab">
        @include('v2-supportconfigs::cms.supportConfigs.tabs.logs')
    </div>
</div>
```

Cada aba é renderizada **sempre** (não há lazy loading); só o `tab-pane` fica oculto. Consequência: a aba Logs já tem o spinner no HTML, mas só busca dados quando o evento `shown.bs.tab` dispara. Também significa que os `<script>` de Suporte/Logs são registrados na página inteira, independentemente da aba ativa.

```blade
{{-- V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/tabs/modulos.blade.php:187-224 — fluxo do switch. --}}
document.querySelectorAll('.module-toggle').forEach(function (checkbox) {
    checkbox.addEventListener('change', function () {
        const module  = this.dataset.module;
        const title   = this.dataset.title, newState = this.checked;
        pendingToggle = { checkbox: this, module: module, title: title, newState: newState };
        if (newState) {
            modalBody.innerHTML =
                '<strong>Ativar módulo?</strong><br>' +
                'Você está prestes a <strong class="text-success">ativar</strong> o módulo ' +
                '<strong>' + title + '</strong> (' + module + ').<br><br>' +
                'O menu e as rotas serão restaurados imediatamente.';
            confirmBtn.className = 'btn btn-success fw-bold d-inline-flex align-items-center gap-1';
            getConfirmTextSpan().textContent = 'Sim, Ativar';
        } else {
            modalBody.innerHTML = /* texto de desativação */;
        }
        modal.show();
    });
});
```

O switch não envia nada sozinho: guarda o estado em `pendingToggle` e abre o modal. O texto usa `title`/`module` vindos de `data-*` — não há escape; um título de módulo com HTML seria injetado (hoje os títulos são estáticos).

```blade
{{-- V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/tabs/modulos.blade.php:238-269 — fetch + atualização do card. --}}
fetch('{{ route('v2.supportconfigs.modules.toggle') }}', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Accept': 'application/json',
               'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
    body: JSON.stringify({ module_key: module, active: newState ? 1 : 0 })
})
.then(function (response) {
    if (!response.ok) { return response.json().then(function (err) { throw err; }); }
    return response.json();
})
.then(function (data) {
    if (data.success) {
        checkbox.checked = newState;
        var card = checkbox.closest('.module-card'); // ... bg-light + cor do .module-icon
    } else {
        checkbox.checked = !newState;
        alert('Erro: ' + (data.message || 'Falha ao alterar módulo.'));
    }
})
```

O `.finally()` restaura o botão, fecha o modal e limpa `pendingToggle`, **mesmo em erro**. Se o `fetch` falhar antes do `then`, o `catch` reverte o checkbox com `alert('Erro de comunicação. Tente novamente.')`.

```blade
{{-- V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/tabs/manutencao.blade.php:17-30 — hidden + switch. --}}
<div class="form-check form-switch mb-0 pt-1">
    <input type="hidden" name="maintenance_mode" value="0">
    <input type="checkbox" id="maintenance_mode" name="maintenance_mode"
           class="form-check-input cursor-pointer" value="1" role="switch"
           style="width: 2.5em; height: 1.5em;"
           {{ ($systemControls['maintenance_mode'] ?? false) ? 'checked' : '' }}>
</div>
```

O par `hidden 0` + `checkbox 1` garante que o campo sempre vá no POST (PHP usa o último valor). Sem o hidden, desmarcar não enviaria a chave e `updateSystemControlsBatch` não desligaria nada. O `role="switch"` está no input, com `label for` associado.

```blade
{{-- V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/tabs/suporte.blade.php:144-158 — detalhe via AJAX. --}}
function showUserDetail(userId) {
    var container = document.getElementById('user-detail-container');
    var content = document.getElementById('user-detail-content');
    container.style.display = 'block';
    content.innerHTML = '<div class="text-center py-5"><span class="spinner-border text-primary mb-3" role="status"></span><p class="text-muted mb-0">Carregando detalhes...</p></div>';

    fetch('/cms/infra/support-configs/users/detail/' + userId, {
        headers: { 'Accept': 'application/json' }
    })
    .then(function(r) { return r.json(); })
    .then(function(user) {
        if (user.error) {
            content.innerHTML = '<div class="alert alert-danger border-0 shadow-sm">' +
                '<i class="bi bi-exclamation-triangle-fill me-1"></i> ' + user.error + '</div>';
            return;
        }
```

O caminho é absoluto na raiz: se o CMS for servido em subdiretório, o `fetch` quebra. O `userId` vem de `onclick="showUserDetail({{ $user['id'] }})"` — sem quotes; um id não numérico quebraria o JS.

```blade
{{-- V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/tabs/logs.blade.php:114-140 — recarga do tail. --}}
function reloadLogs() {
    var viewer = document.getElementById('log-viewer');
    var info = document.getElementById('log-info');
    var btn = document.getElementById('btn-reload-logs');
    var selector = document.getElementById('log-file-selector');
    var selectedFile = selector.value || currentLogFile;
    btn.disabled = true;
    btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span> Carregando...';
    viewer.innerHTML = '<div class="text-center py-5">' +
        '<span class="spinner-border text-light mb-3" role="status" style="width: 2.5rem; height: 2.5rem;"></span>' +
        '<p class="text-secondary small mb-0">Carregando logs...</p></div>';
    var url = '{{ route("v2.supportconfigs.logs.tail") }}?lines=500&_=' + Date.now();
    if (selectedFile) {
        url += '&file=' + encodeURIComponent(selectedFile);
    }

    fetch(url, {
        headers: { 'Accept': 'application/json' }
    })
```

Não há debounce nem cancelamento: trocar o select e clicar em “Recarregar” em sequência dispara duas requisições concorrentes; a última a responder vence. O `_=Date.now()` evita cache do navegador.

```blade
{{-- V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/tabs/logs.blade.php:274-284 — a aba dispara a carga. --}}
document.addEventListener('DOMContentLoaded', function() {
    var tabTrigger = document.querySelector('button[data-bs-target="#tab_logs"]');
    if (tabTrigger) {
        tabTrigger.addEventListener('shown.bs.tab', function() {
            reloadLogs();
        });
    }
    setTimeout(function() {
        var activeTab = document.querySelector('.tab-pane.active');
        if (activeTab && activeTab.id === 'tab_logs') {
            reloadLogs();
        }
    }, 500);
});
```

O `setTimeout(500)` cobre o caso de a página abrir já na aba Logs (por exemplo, após um redirect), mas não há hash/URL que selecione aba; na prática só o evento resolve. Como `shown.bs.tab` é disparado também ao sair e voltar, cada retorno refaz a chamada.

### 2.5 Custos e limites

- **Render**: 4 parciais sempre renderizadas + 1 composer por view do CMS (cada include de `box` dispara `CmsThemeComposer`).
- **JS**: ~120 linhas em Módulos, ~80 em Suporte, ~190 em Logs, todas inline na página (sem minificação).
- **Logs**: 1 requisição por abertura da aba, por clique e por troca de arquivo; resposta pode ter 2000 linhas.
- **Diagnóstico**: consulta drivers de banco e cache a cada abertura.
- **HTML**: cards de módulos são todos renderizados de uma vez; sem paginação.

## 3. Particularidades

### 3.1 O que só existe aqui

- **Sidebar de pills com diagnóstico fixo**: nenhum outro módulo combina navegação lateral de abas com um card de status permanente.
- **Modal de confirmação com texto dinâmico por estado do switch** e recolorização do card sem reload.
- **Visualizador de log com destaque de níveis por regex** e cards de arquivos navegáveis por teclado.
- **Branch de negação no Blade inalcançável** (o controller aborta antes).
- **Modal de senha com campo `type="text"`** (senha visível), não `password`.

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

| ID | Regra | Efeito | Fonte |
|---|---|---|---|
| `RN-SUPPORTCONFIGS-27` | A aba Módulos é a única `active` inicial. | Abrir o painel nunca carrega logs nem busca usuário. | `index.blade.php:111` |
| `RN-SUPPORTCONFIGS-28` | Switch de flag só envia após confirmação no modal; fechar o modal reverte. | Cancelar não altera o banco. | `modulos.blade.php:187-305` |
| `RN-SUPPORTCONFIGS-29` | Cada campo de controle tem `hidden value=0` + checkbox `value=1`. | O POST sempre contém as três chaves; desmarcar grava `'false'`. | `manutencao.blade.php:23-24,54-55,77-78` |
| `RN-SUPPORTCONFIGS-30` | A tabela de usuários lê de `session('search_results')`, não de uma variável do controller. | Resultado só aparece após redirect; F5 perde a lista (flash consumido). | `suporte.blade.php:29` |
| `RN-SUPPORTCONFIGS-31` | O modal de senha usa `minlength=6` no cliente e o mesmo limite no servidor. | JS desabilitado ainda é barrado no servidor. | `suporte.blade.php:115-118`; `SupportConfigsCmsController.php:250-252` |
| `RN-SUPPORTCONFIGS-32` | O select de logs é preenchido **após** o primeiro fetch, com `data.files`. | Antes do primeiro fetch mostra “Carregando...”. | `logs.blade.php:34-38,143-162` |
| `RN-SUPPORTCONFIGS-33` | O formulário de limpeza recebe o arquivo atual via `#clear-log-file`. | Limpar sem selecionar usa o arquivo carregado no viewer. | `logs.blade.php:47-51,141` |
| `RN-SUPPORTCONFIGS-34` | Grupos `SUPPORT` e `OUTROS`/vazios são descartados no Blade. | Flags desses grupos não aparecem, mesmo existindo no banco. | `modulos.blade.php:27-38` |
| `RN-SUPPORTCONFIGS-35` | `FriendlyLogName` calcula “hoje/ontem” por diferença de dias em ms. | Fuso/DST podem rotular errado; nomes fora do padrão aparecem crus. | `logs.blade.php:99-112` |

### 3.3 Casos-limite e estados

| Estado | Onde aparece | Comportamento |
|---|---|---|
| Vazio — módulos | `modulos.blade.php:46-56` | Se todos forem `SUPPORT`/`OUTROS`, a lista fica vazia e nenhuma mensagem é exibida |
| Vazio — busca | `suporte.blade.php:70-77` | Alerta azul com o termo; só aparece se `session('search_term')` existir |
| Vazio — atividades | `suporte.blade.php:198-201` | “Nenhuma atividade registrada.” |
| Vazio — logs | `logs.blade.php:180-184` | `[ LOG VAZIO ]` |
| Carregando — detalhe | `suporte.blade.php:148` | Spinner grande + “Carregando detalhes...” |
| Carregando — logs | `logs.blade.php:30-32,126-129` | Spinner no viewer e no botão |
| Erro — toggle | `modulos.blade.php:281-288` | `alert` e reversão do switch |
| Erro — detalhe | `suporte.blade.php:154-156,203-207` | Alerta vermelho dentro do container |
| Erro — logs | `logs.blade.php:194-198` | Bloco vermelho no viewer; o botão é reabilitado no `.then()` final |
| Sem permissão | `index.blade.php:132-137` | Card “Acesso Negado” — inalcançável via controller |

### 3.4 Armadilhas de reimplementação

- **Não remover o branch de negação do Blade sem remover o `abort`**: hoje ele é morto; se o controller passar a renderizar para não-suporte, o branch vira a única defesa.
- **Não trocar `@push('js')` por `@push('scripts')`** sem conferir o layout: ambos existem (`app.blade.php:140-142`), mas a ordem de renderização muda (scripts antes de js).
- **Não mover o `<script>` para o `<head>`**: ele depende de `bootstrap.Modal` e de elementos já no DOM; o listener está em `DOMContentLoaded`, mas `new bootstrap.Modal(document.getElementById(...))` roda no callback.
- **Não confiar no `finally` para reabilitar o botão em todos os browsers**: `Promise.finally` não existe em navegadores antigos; o código não tem polyfill.
- **Não usar o mesmo `name` sem o hidden**: sem `value=0`, desmarcar não envia e o controle não desliga.
- **Não assumir que a aba Logs carrega ao abrir a página**: só carrega no evento; F5 na aba ativa depende do `setTimeout(500)`.
- **Não reaproveitar `#user-detail-container` para outro usuário sem limpar**: o conteúdo é substituído, mas o `display:block` permanece.
- **Não remover o `confirm()` achando que o modal cobre**: apenas o toggle tem modal.

### 3.5 Divergências e dívidas

| Divergência | Documentação/comentário | Código | Fonte |
|---|---|---|---|
| “5 abas” | docblock de `index` | 4 abas | `SupportConfigsCmsController.php:57`; `index.blade.php:38-58` |
| “Acesso Negado” | view sugere tratamento | inalcançável (403 antes) | `index.blade.php:10,132-137` |
| Campo de senha | esperado `type="password"` | `type="text"` (senha visível) | `suporte.blade.php:115-118` |
| URL do detalhe | rotas nomeadas | path absoluto hardcoded | `suporte.blade.php:150` |
| Retenção de log | rodapé afirma 30 dias/diário | depende de `APP_LOG=daily` | `logs.blade.php:89-91`; `config/app.php:127-131` |
| Linhas do log | rodapé “500” | servidor aceita 50–2000; UI sempre 500 | `logs.blade.php:90`; `SupportConfigsCmsController.php:271-274` |
| Ícones de grupo | `$groupIcons` em caixa alta | grupos vêm do diretório com inicial maiúscula (`Publicacoes`) → fallback `bi-box-seam` | `modulos.blade.php:8-22,43-47` |
| Classe `min-w-0` | usada como utilitária | é classe Tailwind, não Bootstrap | `modulos.blade.php:82`; `logs.blade.php:232` |
| Filtro do grupo | comentário “grupos vêm dos diretórios” | `module_group` do banco é ignorado | `modulos.blade.php:6,31-40` |

## 4. Integrabilidade

### 4.1 Contrato de DOM/JS

**IDs estáveis**

| ID | Elemento | Papel |
|---|---|---|
| `#support-tabs` | `div.nav.flex-column` | tablist |
| `#tab-modulos-tab`, `#tab-manutencao-tab`, `#tab-suporte-tab`, `#tab-logs-tab` | buttons | gatilhos |
| `#tab_modulos`, `#tab_manutencao`, `#tab_suporte_user`, `#tab_logs` | panes | conteúdo |
| `#toggleConfirmModal` | modal | confirmação de flag |
| `#confirmModalMessage` | `p` | texto dinâmico |
| `#confirmToggleBtn` | button | confirma; contém `#confirmToggleBtnText` |
| `#user-detail-container` | div | wrapper do detalhe |
| `#user-detail-content` | div | injeção de HTML |
| `#passwordResetModal` | modal | reset de senha |
| `#reset_user_id`, `#reset_user_name`, `#new_password` | inputs | dados do reset |
| `#log-file-selector` | select | arquivo atual |
| `#btn-reload-logs` | button | recarrega |
| `#log-info` | span | arquivo/linhas/tamanho |
| `#clear-log-form`, `#clear-log-file` | form/hidden | limpeza |
| `#log-files-summary`, `#log-files-grid`, `#log-files-total` | divs | cards de arquivos |
| `#log-viewer` | div `role="log"` | conteúdo colorido |

**Classes funcionais**: `.module-toggle` (switch), `.module-card` (card do módulo), `.module-icon` (caixa do ícone), `.nav-link`, `.tab-pane`.

**Eventos**

| Evento | Origem | Efeito |
|---|---|---|
| `change` em `.module-toggle` | usuário | abre `#toggleConfirmModal` |
| `click` em `#confirmToggleBtn` | usuário | `fetch` POST toggle |
| `hidden.bs.modal` em `#toggleConfirmModal` | Bootstrap | reverte switch se não confirmado |
| `click` nos cards de log | usuário | seta select + `reloadLogs()` |
| `keydown` Enter/Espaço nos cards | usuário | dispara `click` |
| `shown.bs.tab` em `#tab_logs` | Bootstrap | `reloadLogs()` |
| `DOMContentLoaded` | browser | inicializa listeners e `setTimeout(500)` |

**Funções globais**: `reloadLogs()`, `friendlyLogName(filename)`, `renderFileSummary(files, currentFile)`, `formatBytes(bytes)`, `showUserDetail(userId)`, `showPasswordReset(userId, userName)`. Nenhuma tem namespace; colidem com outras telas que definam os mesmos nomes.

### 4.2 Props/slots das views

| View | Entrada | Obrigatória | Origem |
|---|---|---|---|
| `index` | `$diagnostics` (array de 10 chaves) | sim | controller |
| `index` | `$modules` (array de `{name,title,group,active,icon,description}`) | sim | `getModulesStatus` |
| `index` | `$systemControls` (`maintenance_mode`,`app_debug`,`debugbar_enabled`) | sim | `getSystemControls` |
| `index` | `$history` | não (`?? null`) | controller (sempre `collect()`) |
| `index` | `$logData` | não | só no ramo não-JSON de `getLogTail` (quebra a view) |
| `tabs.modulos` | `$modules` | sim | herdada |
| `tabs.manutencao` | `$systemControls` | sim | herdada |
| `tabs.suporte` | `session('search_results')`, `session('search_term')` | não | flash |
| `tabs.logs` | nenhuma | — | busca via JS |

Todas usam `v2-cms::components.box` com slot `footer` (só Logs usa).

### 4.3 Ordem e ciclo de vida

1. Controller → view container → layout `v2-cms::layouts.app` (aplica `$cmsThemeCss`, `$cmsThemeConfigs`).
2. Sidebar e diagnóstico renderizam; panes renderizam todos os parciais.
3. `@push('modals')` do Módulos é impresso no fim do `<body>` (`app.blade.php:142`); `@push('js')` e `@push('scripts')` idem.
4. `DOMContentLoaded` (Módulos) inicializa o modal imediatamente; (Logs) registra o listener de tab e o timeout; (Suporte) só define funções, sem init.
5. Nenhuma destruição/teardown: listeners morrem com a página; não há SPA.

### 4.4 Receitas de uso

**1) Adicionar uma aba:**

```blade
{{-- index.blade.php: sidebar + pane --}}
<button class="nav-link" id="tab-nova-tab" data-bs-toggle="pill"
        data-bs-target="#tab_nova" type="button" role="tab"
        aria-controls="tab_nova" aria-selected="false">Nova</button>

<div class="tab-pane fade" id="tab_nova" role="tabpanel" aria-labelledby="tab-nova-tab">
    @include('v2-supportconfigs::cms.supportConfigs.tabs.nova')
</div>
```

O controller precisa passar as variáveis da nova aba em `index`; não há registry de abas.

**2) Disparar um toggle programaticamente:**

```js
document.getElementById('toggle-noticias').checked = true;
document.getElementById('toggle-noticias').dispatchEvent(new Event('change', { bubbles: true }));
```

Usa o mesmo caminho do usuário (modal + fetch); não existe API JS pública.

**3) Reutilizar o visualizador de logs em outra tela:** copie o bloco `#log-viewer` + `reloadLogs` e ajuste a URL; não há componente Blade isolado. Prefira extrair um componente se houver reuso real.

**4) Abrir o detalhe de um usuário via console:**

```js
showUserDetail(123);
```

Depende de `#user-detail-container` existir na página e da URL absoluta correta.

**5) Recolorir um card após toggle bem-sucedido:** o código já faz; para novos cards, mantenha as classes `.module-card` e `.module-icon`, pois o JS as procura.

### 4.5 Anti-uso

**1) Colocar um `<form>` em volta do switch de flag.** O switch não deve submeter; o JS intercepta `change` e faz `fetch`. Um form faria POST duplo (form + fetch).

**2) Usar `name="active"` em vez de `module_<key>` no batch.** O endpoint `modules/batch` só lê prefixo `module_`; outros campos são ignorados e a resposta é “Nenhum módulo selecionado…”.

**3) Reutilizar `showUserDetail` em página sem `#user-detail-content`.** `container`/`content` serão `null` e o primeiro `container.style` lança `TypeError`, interrompendo o script.

### 4.6 Custos e limites

- 4 parciais + 4 componentes `box` + composer CMS por view: a tela faz várias consultas de tema.
- Logs: payload até 2000 linhas, com colorização por regex no cliente (6 substituições sobre o texto inteiro).
- Cards de arquivos: `O(n)` de logs com `innerHTML` por card.
- Sem virtualização: logs grandes em `#log-viewer` com `max-height:550px` e `white-space:pre-wrap` podem travar a rolagem.
- Acessibilidade: foco não é gerenciado ao abrir/fechar modais além do que o Bootstrap faz; o viewer tem `aria-live="polite"` e pode anunciar blocos enormes.

## 5. Rotas e contratos HTTP

Resumo; detalhe em `rotas.md` §5. A UI usa:

| Ação | Rota | Método | Formato |
|---|---|---|---|
| Limpar cache | `v2.supportconfigs.clear_cache` | POST | form |
| Toggle | `v2.supportconfigs.modules.toggle` | POST | fetch JSON |
| Controles | `v2.supportconfigs.system_controls.save` | POST | form |
| Buscar | `v2.supportconfigs.users.search` | GET | form |
| Detalhe | `v2.supportconfigs.users.detail` | GET | fetch JSON (URL hardcoded) |
| Reset senha | `v2.supportconfigs.users.reset_password` | POST | form |
| Tail | `v2.supportconfigs.logs.tail` | GET | fetch JSON |
| Limpar log | `v2.supportconfigs.logs.clear` | POST | form |

Nenhuma chamada define `throttle`, timeout ou retry. CSRF: forms via `csrf_field()`; toggle via header; GETs não precisam.

## 6. Dados e modelo de domínio

| Campo de UI | Chave/tabela | Escrita | Fonte |
|---|---|---|---|
| Switch de módulo | `v2_module_flags.active` | `toggleModule` | `modulos.blade.php:93-104` |
| Manutenção | `v2_system_controls.maintenance_mode` | `updateSystemControl` | `manutencao.blade.php:20-35` |
| APP_DEBUG | `v2_system_controls.app_debug` | idem | `manutencao.blade.php:51-66` |
| Debugbar | `v2_system_controls.debugbar_enabled` | idem | `manutencao.blade.php:74-89` |
| Nova senha | `users.password` | `Sentinel::update` | `suporte.blade.php:105-121` |
| Arquivo de log | filesystem `storage/logs` | `clearLogFile` | `logs.blade.php:47-51` |

A tela **não** escreve `v2_portal_configs`, `v2_cms_theme_configs` nem `v2_system_mail_configs`; apenas exibe dados derivados (`diagnostics`) e o resultado de `modules`/`systemControls`.

## 7. Fluxos e estados

```mermaid
stateDiagram-v2
  [*] --> Modulos
  Modulos --> ModalFlag: change no switch
  ModalFlag --> Modulos: cancelar (reverte)
  ModalFlag --> Salvando: confirmar
  Salvando --> Modulos: 200 success (recolore)
  Salvando --> Modulos: erro (reverte + alert)
  Modulos --> Manutencao: clique na pill
  Manutencao --> Modulos: POST + reload
  Modulos --> Suporte: clique na pill
  Suporte --> Detalhe: olho (fetch)
  Suporte --> ModalSenha: chave
  ModalSenha --> Suporte: POST + reload
  Modulos --> Logs: clique na pill
  Logs --> CarregandoLog: shown.bs.tab
  CarregandoLog --> Logs: 200 (viewer + cards)
  CarregandoLog --> Logs: erro (bloco vermelho)
```

## 8. UI CMS

### 8.1 Tela única

| Item | Valor |
|---|---|
| Rota | `GET /cms/infra/support-configs` |
| Permissão | e-mail de suporte (controller); middleware não aplica RBAC |
| Layout | `v2-cms::layouts.app`, título “Configurações” |
| Breadcrumb | Dashboard (`v2.cms.dashboard`) → Suporte (`v2.supportconfigs.index`) → Configurações |
| Objetivo | operar o sistema |
| Colunas | 3/12 sidebar + diagnóstico; 9/12 abas |
| Estados | 4 abas; vazios/erros por aba (§3.3) |
| Flash | `success` e `error`, dismissíveis |

### 8.2 Aba 1 — Módulos (Feature Flags)

**Objetivo**: ligar/desligar módulos. **Rota de escrita**: toggle AJAX.

| Campo | Tipo | Obrigatório | Default | Validação | Ajuda | Visibilidade |
|---|---|---|---|---|---|---|
| Switch por módulo | checkbox | — | `$mod['active']` | — | texto do modal | todos exceto grupo `SUPPORT`/`OUTROS` |

- Cabeçalho por grupo com ícone, nome em maiúsculas e badge `X/Y ativos` (`modulos.blade.php:43-58`).
- Card mostra ícone, título, `name` em monospace e descrição; inativo recebe `bg-light` e ícone cinza (`:60-106`).
- Textos do modal: “Ativar módulo?” / “Desativar módulo?”; botões “Sim, Ativar”/“Sim, Desativar”; rodapé “Cancelar”; título “Confirmar Alteração” (`:140-170,196-218`).
- Alerta final: “Módulos ativos aparecem na barra lateral do CMS e têm suas rotas disponíveis. Ao desativar um módulo, ele é ocultado do menu e o acesso às suas rotas é bloqueado. Nenhuma configuração ou dado é perdido. Módulos da categoria SUPPORT são sempre ativos e não aparecem nesta lista.” (`:116-130`).
- Mensagens de erro: `alert('Erro: ' + message)` / `alert('Erro de comunicação. Tente novamente.')` (`:281-288`).
- Acessibilidade: `label.visually-hidden` por switch; `aria-hidden` nos ícones; modal com `aria-labelledby`, `data-bs-backdrop="static"`, `data-bs-keyboard="false"`.

### 8.3 Aba 2 — Sistema & Manutenção

**Objetivo**: alternar manutenção e debug. **Rota**: `system-controls/save` (POST).

| Campo | Nome | Tipo | Default | Validação | Ajuda exibida |
|---|---|---|---|---|---|
| Modo de manutenção | `maintenance_mode` | hidden 0 + switch 1 | `$systemControls['maintenance_mode']` | — | “Ativa o banner vermelho no topo do CMS e exibe a página de manutenção no portal público.” |
| APP_DEBUG | `app_debug` | idem | idem | — | “Quando ativo, erros 500 mostrarão a stack trace completa (Ignition/Whoops).” |
| Debugbar | `debugbar_enabled` | idem | idem | — | “Exibe a barra inferior de profiling de queries e performance.” |

- Botão “Aplicar Controles de Sistema”.
- Alerta amarelo: manutenção mantém CMS logado com banner; APP_DEBUG só em dev (`manutencao.blade.php:95-109`).
- **Risco**: um clique liga manutenção no portal inteiro; não há confirmação nem digest de impacto. APP_DEBUG expõe stack traces/segredos.
- O banner prometido é renderizado fora deste módulo: `V2/layouts/cms/layouts/maintenance-banner.blade.php:1-5` é incluído por `V2/layouts/cms/layouts/app.blade.php:58-59` e chama `v2_is_maintenance_active()` em toda tela que usa esse layout.

### 8.4 Aba 3 — Suporte de Usuários

**Objetivo**: localizar conta, inspecionar e forçar senha.

| Campo | Tipo | Obrigatório | Default | Validação cliente | Validação servidor |
|---|---|---|---|---|---|
| `q` | text | sim | `session('search_term')` | `minlength=2`, `required` | `<2` → flash/JSON vazio |
| `user_id` | hidden | sim | preenchido por JS | — | vazio → erro |
| `new_password` | text | sim | `''` | `minlength=6`, `required` | `strlen < 6` → erro |

- Tabela: `#`, Nome, E-mail (`<code>`), Papéis, Último Login, Ações (olho/chave) (`suporte.blade.php:31-68`).
- Detalhe: `<dl>` com ID, Nome, E-mail, Papéis, Último Login, Criado em + tabela “Últimas Atividades” (Data, Ação, Alvo) (`:157-197`).
- Modal “Resetar Senha”: usuário, campo “Nova Senha”, ajuda “Mínimo de 6 caracteres. A senha será alterada imediatamente…”, botão com `confirm('Tem certeza que deseja forçar o reset de senha?')` (`:99-140`).
- Acessibilidade: `aria-label` nos botões e na tabela, `aria-describedby="passwordHelp"`, `aria-hidden` nos ícones.
- **Risco**: não há indicação de que a senha é visível; o campo é `type="text"`.

### 8.5 Aba 4 — Logs

**Objetivo**: ler/truncar logs sem SSH.

| Controle | ID | Comportamento |
|---|---|---|
| Select de arquivo | `#log-file-selector` | `onchange="reloadLogs()"`; rótulos amigáveis (“Log Atual (data)”, “Log Ontem (data)”) |
| Recarregar | `#btn-reload-logs` | spinner enquanto busca |
| Info | `#log-info` | `arquivo — N linhas — tamanho` |
| Limpar log | form `#clear-log-form` | `confirm('LIMPAR O ARQUIVO DE LOG?\n\nUm backup será gerado automaticamente antes da limpeza.')` |
| Cards | `#log-files-grid` | resumo por arquivo, clique/Enter/Espaço |
| Viewer | `#log-viewer` | `role="log"`, `aria-live="polite"`, fundo `#1e1e1e` |

- Destaques: `[ERROR]/[CRITICAL]/[ALERT]/[EMERGENCY]` vermelho; `[WARNING]` amarelo; `[INFO]` verde; `[DEBUG]` azul; `stack trace:` roxo; datas azul (`logs.blade.php:166-179`).
- Rodapé: “Exibindo as últimas 500 linhas… Rotação diária automática com retenção de 30 dias.” (`:85-92`).
- Aviso de segurança com o e-mail de suporte (`:10-20`).
- **Risco**: mostra stack traces e SQL; o conteúdo é sanitizado por `DOMPurify` se disponível.

### 8.6 Diagnóstico (card fixo)

`SystemDiagnosticsService::getDiagnostics()` devolve (`SystemDiagnosticsService.php:38-54`):

| Rótulo | Chave | Origem | Efeito de “Limpar Cache” |
|---|---|---|---|
| PHP | `php_version` | `PHP_VERSION` | — |
| Laravel | `laravel_version` | `app()->version()` | — |
| Ambiente | `environment` | `app()->environment()` | — |
| Debug | `debug_mode` | `config('app.debug')` | não reflete o toggle de `app_debug` |
| Cache | `cache_driver` | `config('cache.default')` | — |
| Sessão | `session_driver` | `config('session.driver')` | — |
| Fila | `queue_driver` | `config('queue.default')` | — |
| BD | `db_driver`, `db_name` | conexão padrão | — |
| Último Cron | `last_cron_run` | `Cache::get('last_cron_run','Nunca')` | **volta a “Nunca”** |

Botão “Limpar Cache” (`confirm('Limpar cache do sistema?')`) chama `clearSystemCache()` → `cache:clear`, `config:clear`, `view:clear` + auditoria `cache_cleared` (`SystemMaintenanceService.php:47-63`). Risco: apaga o cache de página e a chave `last_cron_run`; não apaga logs nem configurações. Não há confirmação de segundo nível.

## 9. UI Portal

Não se aplica: a tela é exclusiva do CMS. As variáveis que o painel altera e que afetam o portal (`$portalTheme`, `$portalConfigs`) estão em `dados.md` §6.5.

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

- **Quem vê a tela**: `CmsAuthenticate` (Sentinel + papel) e o controller (e-mail). O Blade repete a checagem.
- **Ocultação no menu**: `SidebarComposer` remove grupo `Support` para não-suporte e aplica `restricted` (`SidebarComposer.php:30-68`).
- **Permissão de escrita**: nenhuma por módulo; qualquer ação passa pela guarda de e-mail, exceto a rota R11 (fora desta tela em termos de controller, mas acionada por form oculto da SLE).
- **Flags**: a tela lista todas as flags exceto `Support`/`Outros`; a flag `supportconfigs` (que controla o próprio painel) não é listada.
- **Config**: nenhuma chave de `config/v2.php` é editável aqui; `v2.support.email` é apenas exibida na aba Logs.

## 11. Observabilidade, erros e limites

- **Erros de JS**: não há handler global; falha em `fetch` cai no `.catch` de cada bloco.
- **Erros de servidor**: flash `error` ou `alert`; `403`/`404` viram páginas de erro.
- **Auditoria**: cada ação deixa rastro (§11 de `spec.md`); a tela não exibe o histórico (`$history` é `collect()`).
- **Logs de aplicação**: ver `spec.md` §11.
- **Limites**: 500 linhas fixas, 20 usuários, senha ≥6, favicon 100 KB (fora desta tela), sem throttle.

## 12. Seeds e dados iniciais

Não se aplica: a tela não cria seeds; ela depende dos seeds de `dados.md` §12 (flags/controles) para ter conteúdo. Com tabelas vazias, mostra módulos todos ativos (default) e controles desligados.

## 13. Lacunas

- `LG-SUPPORTCONFIGS-15`: não foi possível enumerar quais telas do CMS **não** usam `v2-cms::layouts.app` (ex.: login) e, portanto, não exibem o banner de manutenção mesmo com `maintenance_mode='true'`. Procurar em `UI-CMS`. Impacto: baixo (cosmético/operacional).
- `LG-SUPPORTCONFIGS-16`: `DOMPurify` não é carregado pelo módulo; depende de o layout global incluí-lo. Procurar em `V2/layouts/cms/layouts/app.blade.php`. Impacto: baixo (fallback `textContent`).
- `LG-SUPPORTCONFIGS-17`: não foi possível confirmar se `bootstrap` global (5.x) está sempre disponível em todas as telas; o modal depende dele. Procurar no layout/asset pipeline.
- `LG-SUPPORTCONFIGS-18`: não há teste de UI/JS; todos os fluxos foram lidos do código.
- `LG-SUPPORTCONFIGS-19`: `tabs/suporte.blade.php` e `tabs/logs.blade.php` usam `@push('scripts')`, enquanto `modulos` usa `@push('js')`; a ordem de execução entre os dois stacks não foi validada em runtime. Procurar em `UI-CMS` §stacks.

## 14. Checklist de paridade

- [ ] `PC-SUPPORTCONFIGS-41` — Abrir o painel → 4 pills, `#tab_modulos` ativa, diagnóstico com 9 rótulos e “Último Cron”.
- [ ] `PC-SUPPORTCONFIGS-42` — Trocar para a aba Logs → `fetch` para `logs/tail?lines=500` disparado uma vez; select preenchido com os arquivos retornados.
- [ ] `PC-SUPPORTCONFIGS-43` — Alternar um switch e cancelar o modal → nenhuma requisição e switch revertido.
- [ ] `PC-SUPPORTCONFIGS-44` — Alternar e confirmar → um POST JSON; card perde/ganha `bg-light`; ícone muda de cor; modal fecha.
- [ ] `PC-SUPPORTCONFIGS-45` — Forçar erro (flag desativada) → switch reverte e `alert` com a mensagem do servidor.
- [ ] `PC-SUPPORTCONFIGS-46` — Desmarcar “Modo de Manutenção” e salvar → POST contém `maintenance_mode=0`; banco grava `'false'`.
- [ ] `PC-SUPPORTCONFIGS-47` — Buscar usuário com 2+ caracteres → tabela com colunas e botões; olho abre detalhe; chave abre modal.
- [ ] `PC-SUPPORTCONFIGS-48` — Detalhe de usuário com 0 atividades → “Nenhuma atividade registrada.”
- [ ] `PC-SUPPORTCONFIGS-49` — Modal de senha com 5 caracteres → botão nativo bloqueia; com 6 → POST e flash de sucesso.
- [ ] `PC-SUPPORTCONFIGS-50` — Viewer de logs colore `[ERROR]`, `[WARNING]`, `[INFO]`, `[DEBUG]`, `stack trace:` e datas.
- [ ] `PC-SUPPORTCONFIGS-51` — Clicar em um card de arquivo → select muda e `reloadLogs()` busca aquele arquivo.
- [ ] `PC-SUPPORTCONFIGS-52` — “Limpar Log” → `confirm()` com o texto exato; ao confirmar, POST e flash de sucesso.
- [ ] `PC-SUPPORTCONFIGS-53` — Grupo `SUPPORT` e grupo `OUTROS` não aparecem na lista de módulos; badge `X/Y ativos` bate com os visíveis.
- [ ] `PC-SUPPORTCONFIGS-54` — “Limpar Cache” → `confirm` e, após o redirect, Último Cron = “Nunca”.
- [ ] `PC-SUPPORTCONFIGS-55` — Flash `success`/`error` dismissível com `aria-label="Fechar"` e `<h4>` “Sucesso!”/“Erro!”.

## 15. Evidências consultadas

- `V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/index.blade.php:1-142`
- `V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/tabs/modulos.blade.php:1-324`
- `V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/tabs/manutencao.blade.php:1-114`
- `V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/tabs/suporte.blade.php:1-214`
- `V2/Modules/Support/SupportConfigs/Views/cms/supportConfigs/tabs/logs.blade.php:1-284`
- `V2/Modules/Support/SupportConfigs/Controllers/SupportConfigsCmsController.php:59-303`
- `V2/Modules/Support/SupportConfigs/Services/SystemDiagnosticsService.php:38-153`
- `V2/Modules/Support/SupportConfigs/Services/SystemMaintenanceService.php:47-63,357-430`
- `V2/Modules/Support/SupportConfigs/Services/UserManagementService.php:38-145`
- `V2/Modules/Support/SupportConfigs/ViewComposers/CmsThemeComposer.php:25-135`
- `V2/layouts/cms/layouts/app.blade.php:1-46,136-142`
- `V2/Core/ViewComposers/SidebarComposer.php:18-75`
- `V2/Core/Middleware/CmsAuthenticate.php:18-44`
- `V2/Modules/Support/StructuralLandingEditor/Views/cms/submodules/theme/index.blade.php:88-104`
- `V2/Modules/Support/StructuralLandingEditor/Views/cms/tabs/userconfigs/tema-cms.blade.php:150-165`
- `_qa/security-g1.md:79-94`
