# Logs do Sistema — Gaps, Dívidas e Divergências v5 → v6

> Levantamento de problemas conhecidos, funcionalidades mortas, riscos de
> dados e perguntas em aberto do módulo de logs do sistema.

---

## 1. A duplicidade do slug `logs-do-sistema`

### 1.1 Como ela nasceu

`v6/database/migrations/2024_11_01_150206_create_modulos_table.php` insere
o mesmo slug **duas vezes**, em dois blocos diferentes da migration:

```php
// ---- Cofigurações ---- //
// ID 7
DB::table('modulos')->insert([
    'name' => 'Logs do Sistema',
    'slug' => 'logs-do-sistema',
    'status' => 1,
]);
...
// ---- Sidebar ---- //
// ID 32
DB::table('modulos')->insert([
    'name' => 'Logs do Sistema',
    'slug' => 'logs-do-sistema',
    'status' => 0,
]);
```

A migration tem **58** linhas de insert (o contrato do dossiê menciona 56
— a contagem real do banco é 58, com **2** slugs duplicados no total:
`logs-do-sistema` e, semanticamente, `diario-ofifical` (id 16) vs
`diario-oficial` (id 37)).

Não há índice `UNIQUE` em `modulos.slug`, o que permitiu e continua
permitindo a duplicação.

### 1.2 Consequências (todas verificadas)

| # | Consequência | Onde |
|---|---|---|
| C1 | `$modulos['logs-do-sistema']` vale sempre `false` | `pluck('status','slug')` resolve a chave duplicada em favor da última linha (id 32). Ocorre em `v6/resources/views/vendor/adminlte/page.blade.php:115-124` **e** em `v6/app/Providers/ModulosServiceProvider.php:22-24` |
| C2 | O item de menu "Logs do sistema" **nunca** é exibido, nem para `super-admin` | `v6/resources/views/vendor/adminlte/page.blade.php:284` |
| C3 | A permissão `registro-de-atividades.index` exigida no menu **não existe** em `resources` | consulta à tabela `resources` |
| C4 | A linha "Logs do Sistema" **não aparece** na matriz de permissões | `resources.id = 36` aponta para `modulo_id = 32` (`status = false`) e `v6/resources/views/admin/role/form.blade.php:43` filtra por módulo ativo |
| C5 | A tela `/cms/modulos` mostra **duas linhas idênticas**, com `id` HTML duplicado | `v6/resources/views/admin/modulos/form.blade.php:32-48` |
| C6 | Ativar uma das linhas não resolve | `ModulosController@update` atualiza cada id separadamente; o `pluck` continua resolvendo pela última linha |
| C7 | O portal público e o dashboard recebem `false` para o módulo | `ModulosServiceProvider` |

**Estado observável**: o módulo **funciona** (grava e lê logs
corretamente) e é acessível por URL direta (`/cms/log`), mas é
**invisível** para o operador e **inacessível** por menu. Na prática, a
funcionalidade de auditoria está desligada para o uso cotidiano.

### 1.3 Correção proposta

1. Migration que mova `resources.modulo_id` do id 32 para o id 7 e apague
   a linha 32 (ou, alternativamente, que **ative** o id 32 e apague o 7).
2. `UNIQUE (slug)` em `modulos`.
3. Criar o recurso `registro-de-atividades` (ou trocar a checagem do menu
   para `logs-do-sistema.index`, alinhando com o slug do recurso).

---

## 2. Bugs e erros conhecidos

| Sev. | Item | Arquivo / linha |
|---|---|---|
| **CRÍTICO** | Slug duplicado → módulo invisível (item 1) | `v6/database/migrations/2024_11_01_150206_create_modulos_table.php` |
| **ALTO** | `Route::resource('log', ...)` gera 6 actions inexistentes (HTTP 500) | `v6/routes/basepro.php:71` |
| **ALTO** | Ordenação invertida: `orderBy('created_at','desc')->orderBy('created_at')` → SQL `ASC`, e o `LIMIT 5000` corta os **mais antigos** | `v6/app/Http/Controllers/Prefecture/DatatableController.php:525` |
| **ALTO** | `LIMIT 5000` sem paginação server-side, sem filtro, sem exportação | `v6/app/Http/Controllers/Prefecture/DatatableController.php:523-527` |
| **MÉDIO** | `json_decode($properties)` sem checar `null` → warning/fatal em PHP 8 | `v6/app/Http/Controllers/Prefecture/DatatableController.php:535` |
| **MÉDIO** | Nenhuma permissão restringe a leitura da trilha | `v6/app/Http/Controllers/Admin/ActivityLogController.php:17-21` |
| **MÉDIO** | `SupportController` grava sem `causedBy` → `causer_id` nulo | `v6/app/Http/Controllers/Prefecture/SupportController.php:113-116` |
| **MÉDIO** | `subject_id` quase sempre nulo (`performedOn` recebe uma instância nova do model) | `v6/app/Http/Controllers/Admin/UserController.php:39` e equivalentes |
| **MÉDIO** | Regex do user-agent fixo em `Chrome/130.0.0.0` | `v6/app/Observers/ActivityObserver.php:22` |
| **MÉDIO** | `log_name` sempre `'default'` → índice inútil, sem classificação de ação | todas as chamadas `activity()` |
| **BAIXO** | Coluna "ID" da tabela mostra um índice sequencial, não o `id` do registro | `struct_logs()` |
| **BAIXO** | `RouteController@destroy` (role) grava "Exclusão de permissão" | `v6/app/Http/Controllers/Admin/RoleController.php:183-184` |
| **BAIXO** | `UpdateLogs` tem `description` no `$fillable` sem a coluna na tabela | `v6/app/Http/Model/Prefecture/UpdateLogs.php:11-19` |
| **BAIXO** | Imports não utilizados (`ActivityLog`, `Sentinel`) | `v6/app/Http/Controllers/Admin/ActivityLogController.php:5-6` |
| **BAIXO** | Purga de logs não agendada (apenas `reload:evacina` é scheduled) | `v6/app/Console/Kernel.php:26-29` |
| **BAIXO** | "Logs dos Sistema" (gramática) no título | `v6/resources/views/admin/activities-logs/index.blade.php:9` |

---

## 3. Funcionalidades incompletas ou mortas

| Item | Situação |
|---|---|
| `Admin\ActivityLogController@create/store/show/edit/update/destroy` | Não existem. Rotas geradas e quebradas. |
| `activitylog:clean` | Comando do pacote disponível, **nunca** agendado. |
| Trait `LogsActivity` no `App\Admin\User` | **Comentado** (`v6/app/Http/Model/Admin/User.php:43`) — a auditoria automática por model nunca foi ativada. |
| Permissão de leitura de logs | Inexistente. Nenhum papel tem permissão específica. |
| Exportação de logs | Inexistente. |
| Filtro por período / autor / ação | Inexistente. |
| `update_logs` como "log do sistema" | Nome enganoso: é o histórico de **versões do software**, não de ações. Mantido separado, mas consumido no mesmo rodapé. |

---

## 4. Mapa v5 → v6

### 4.1 O que mudou

| Aspecto | v5 | v6 |
|---|---|---|
| `Admin\ActivityLogController` | idêntico | **idêntico** |
| `admin/activities-logs/index.blade.php` | idêntico | **idêntico** |
| `public/assets/js/custom/config/logs/datatable.js` | idêntico | **idêntico** |
| `app/Http/Model/Admin/ActivityLog.php` | idêntico | **idêntico** |
| Tabela `activity_log` | mesma migration | mesma migration |
| Colunas `ip_address` / `browser` | **inexistentes** | adicionadas por `2025_01_16_210444_add_ip_address_to_activity_log.php` |
| `app/Observers/ActivityObserver.php` | **inexistente** | **novo** — preenche IP e navegador |
| Registro de módulos (`modulos`) | **inexistente** | **novo** — e é ele que introduz a duplicidade |
| Item de menu "Logs do sistema" | dependia apenas de `has_access` | passou a depender de `$modulos['logs-do-sistema']` **e** de `has_access(['registro-de-atividades.index'])` → **quebrado** |
| Tela `/cms/modulos` | inexistente | nova (expõe as duas linhas duplicadas) |
| `resources.modulo_id` | inexistente | novo (amarra o recurso ao módulo) |
| Paginação / filtros / exportação | inexistentes | **continuam inexistentes** |

### 4.2 Conclusão

O módulo **funcionalmente não evoluiu** da v5 para a v6 — o código é
byte-a-byte idêntico. As duas adições da v6 (IP/navegador e registro de
módulos) **melhoraram** a auditoria, mas a segunda introduziu a duplicidade
que **quebrou o acesso pelo menu**. É um caso claro de regressão
funcional causada por uma mudança de infraestrutura.

---

## 5. Riscos de dados

| Risco | Detalhe | Mitigação |
|---|---|---|
| Duplicidade em `modulos.slug` | Sem `UNIQUE`; outras duplicidades podem existir | auditoria de todos os pares `(slug)`; adicionar `UNIQUE` |
| FK `resources.modulo_id` | Apagar a linha errada quebra a integridade referencial | mover a FK antes de apagar; testar em staging |
| `activity_log.properties` em `text` | Pode conter JSON inválido; a conversão para `jsonb` falha | validar as linhas antes; `NULL` → `'{}'` |
| Volume sem índice em `created_at` | A consulta de listagem faz full scan + sort | indexar `created_at` antes de crescer |
| Ausência de purga | A tabela cresce sem limite | agendar `activitylog:clean` |
| `subject_id` nulo em boa parte dos registros | a informação do "objeto afetado" se perde | backfill impossível; corrigir a gravação a partir de agora |
| Conflito entre `activity_log` e `update_logs` | scripts externos podem ler a tabela errada | documentar claramente a separação; manter nomes distintos |

---

## 6. Perguntas em aberto para o negócio

1. **A duplicidade foi intencional?** A posição na migration (bloco
   "Configurações" x bloco "Sidebar") sugere engano, mas é preciso
   confirmar com quem escreveu a migration.
2. **Quem deve ler a trilha?** Sugestão: um perfil dedicado "auditor",
   com `logs-do-sistema.index` e `logs-do-sistema.export`.
3. **Qual a retenção exigida?** 365 dias (padrão do pacote) é adequado?
   A LGPD e a legislação municipal podem exigir outro prazo.
4. **Deve haver log de tentativas de acesso negado?** Hoje um operador
   sem permissão recebe um flash, e nada é registrado.
5. **A trilha deve ser exposta no portal (transparência)?** Se sim, é
   preciso decidir o que é público (ações de publicação) e o que não é
   (e-mails, senhas, dados pessoais).
6. **`update_logs` e `activity_log` devem ser unificados?** Hoje o rodapé
   do CMS mostra a versão; a tela de Novidades mostra o changelog. São
   três informações parecidas em três lugares.
7. **O que fazer com as linhas antigas** (com `subject_id` nulo e sem
   `ip_address`)? Arquivar em tabela histórica?

---

## 7. Checklist de correção (priorizado)

| Prioridade | Item | Arquivo |
|---|---|---|
| P0 | Consolidar o slug duplicado + `UNIQUE (slug)` | nova migration |
| P0 | Mover `resources.modulo_id` do recurso 36 para o módulo ativo | nova migration |
| P0 | Alinhar a permissão do menu (`registro-de-atividades.index` x `logs-do-sistema.index`) | `v6/resources/views/vendor/adminlte/page.blade.php:284` |
| P0 | Corrigir a ordenação (remover o `orderBy` redundante) | `v6/app/Http/Controllers/Prefecture/DatatableController.php:525` |
| P1 | Remover as 6 rotas inexistentes (`Route::resource` → `Route::get`) | `v6/routes/basepro.php:71` |
| P1 | Paginação server-side + filtros | `v6/app/Http/Controllers/Prefecture/DatatableController.php` |
| P1 | Checagem de permissão na leitura | `v6/app/Http/Controllers/Admin/ActivityLogController.php` |
| P1 | Corrigir `json_decode` de `properties` nulo | `v6/app/Http/Controllers/Prefecture/DatatableController.php:535` |
| P2 | Preencher `causedBy` no `SupportController` | `v6/app/Http/Controllers/Prefecture/SupportController.php:113` |
| P2 | Regularizar o regex do user-agent | `v6/app/Observers/ActivityObserver.php:20-24` |
| P2 | Agendar `activitylog:clean` | `v6/app/Console/Kernel.php:26` |
| P2 | Corrigir o texto "Exclusão de permissão" em `RoleController@destroy` | `v6/app/Http/Controllers/Admin/RoleController.php:184` |
| P3 | Remover `description` do `$fillable` de `UpdateLogs` | `v6/app/Http/Model/Prefecture/UpdateLogs.php:11-19` |
| P3 | Remover imports não utilizados | `v6/app/Http/Controllers/Admin/ActivityLogController.php:5-6` |
| P3 | Corrigir o título "Logs dos Sistema" | `v6/resources/views/admin/activities-logs/index.blade.php:9` |
