# Novidades — Gaps, Dívidas e Divergências v5 → v6

> Módulo **novo na v6**. O levantamento abaixo cobre os problemas
> introduzidos na criação do changelog.

---

## 1. Bugs e erros conhecidos

| Sev. | Item | Arquivo / linha |
|---|---|---|
| **CRÍTICO** | A rota `changelog.show` aponta para um método **inexistente** -> HTTP 500 | `v6/routes/basepro.php:76` + `v6/app/Http/Controllers/Admin/ChangeLogController.php` |
| **ALTO** | O módulo **não tem recurso** em `resources` -> `changelog.index`/`edit`/`delete` não podem ser concedidas; só `super-admin` tem acesso à edição | `v6/database/seeds/` (nenhum seeder de recurso `changelog`) |
| **ALTO** | `catch (\Exception $e) {}` **vazio** -> data em formato inesperado causa erro 500 | `v6/app/Http/Controllers/Admin/ChangeLogController.php:47-52,88-93` |
| **ALTO** | HTML do título e da descrição injetados com `innerHTML` (sem sanitização no servidor) -> XSS armazenado | `v6/public/assets/js/custom/config/novidades/changelog-modal.js` |
| **MÉDIO** | HTML quebrado na listagem: o `@if (has_access(['changelog.index']))` envolve o `</div>` da coluna | `v6/resources/views/prefecture/configurations/changelog/index.blade.php:11-100` |
| **MÉDIO** | Divergência de validação do título: `maxlength="150"` (cliente) x `max:120` (servidor) | `v6/resources/views/prefecture/configurations/changelog/form.blade.php` |
| **MÉDIO** | `numero_versao` sem validação de formato/tamanho no servidor (apenas `required`) | `v6/app/Http/Requests/ChangeLogRequest.php` |
| **MÉDIO** | `data_versao` validado só como `required` (sem `date`) | `v6/app/Http/Requests/ChangeLogRequest.php` |
| **MÉDIO** | Listagem sem paginação: `ChangeLog::orderBy('id','DESC')->get()` carrega tudo | `v6/app/Http/Controllers/Admin/ChangeLogController.php:16` |
| **MÉDIO** | Ordenação por `id`, não por data: uma novidade com data antiga aparece no topo | `v6/app/Http/Controllers/Admin/ChangeLogController.php:16` |
| **MÉDIO** | `ChangeLog` não usa `SoftDeletes`, apesar da coluna `deleted_at` existir -> exclusão definitiva | `v6/app/Http/Model/Admin/ChangeLog.php` |
| **MÉDIO** | `store` grava campo a campo e `update` usa `update($data)` -> assimetria de tratamento | `v6/app/Http/Controllers/Admin/ChangeLogController.php:53-58,94` |
| **BAIXO** | `str_limit` foi removido no Laravel 6 | `v6/resources/views/prefecture/configurations/changelog/index.blade.php:44,47` |
| **BAIXO** | `$dates` foi removido no Laravel 6 (usar `casts`) | `v6/app/Http/Model/Admin/ChangeLog.php` |
| **BAIXO** | `ChangeLog` sem `protected $table` (inferido do nome da classe) | `v6/app/Http/Model/Admin/ChangeLog.php` |
| **BAIXO** | `UpdateLogs` tem `description` no `$fillable` sem a coluna na tabela | `v6/app/Http/Model/Prefecture/UpdateLogs.php:11-19` |
| **BAIXO** | `UpdateVersion` usa `explode('.')` sem validar 3 segmentos | `v6/app/Console/Commands/UpdateVersion.php:47-50` |
| **BAIXO** | `ChangeLogTableSeeder` faz `truncate` — apaga novidades cadastradas manualmente | `v6/database/seeds/ChangeLogTableSeeder.php` |
| **BAIXO** | Nenhuma chamada a `activity()`: as novidades não são auditadas | `v6/app/Http/Controllers/Admin/ChangeLogController.php` |
| **BAIXO** | O item de menu "Novidades" não tem guarda `$modulos['novidades']` | `v6/resources/views/vendor/adminlte/page.blade.php:310-317` |
| **BAIXO** | Namespace inconsistente: controller em `Admin`, views em `prefecture/configurations/changelog/` | — |
| **BAIXO** | Migration de alteração com indentação fora do padrão | `v6/database/migrations/2025_09_26_103213_alter_number_versao_to_string_in_change_logs_table.php` |

---

## 2. Funcionalidades incompletas ou mortas

| Item | Situação |
|---|---|
| `ChangeLogController@show` | Não existe; a rota `changelog.show` existe |
| Recurso `changelog` em `resources` | **Ausente** — nenhuma permissão concedível |
| Auditoria (`activity()`) | Inexistente |
| Paginação / filtro da timeline | Inexistente |
| Exportação | Inexistente |
| Autor / aprovação da novidade | Inexistente (o modelo tem `author_id` só na proposta de migração) |
| Anexos (PDF de release notes) | Inexistentes |
| Versão do sistema x changelog | Duas fontes independentes, sem sincronização |
| Changelog público no portal | Inexistente (é interno) |

---

## 3. Mapa v5 → v6

O módulo **não existe na v5**. Tudo é novidade da v6.

| Aspecto | v5 | v6 |
|---|---|---|
| Controller | inexistente | `Admin\ChangeLogController` (105 linhas) |
| Model | inexistente | `App\Admin\ChangeLog` |
| Form Request | inexistente | `ChangeLogRequest` |
| Tabela | inexistente | `change_logs` (migration `2022_04_22_094515`) |
| Tipo de `numero_versao` | — | `float` -> `varchar(20)` (migration de 2025-09-26) |
| Views | inexistentes | `prefecture/configurations/changelog/**` (5 arquivos) |
| JS | inexistente | `public/assets/js/custom/config/novidades/changelog-modal.js` |
| Seed | inexistente | `ChangeLogTableSeeder` (~28 versões) |
| Versão do sistema | inexistente | `update_logs` (migration `2023_03_22_095658`) + comando `update:logs` + rodapé do CMS e do portal |
| Registro de módulos | inexistente | `modulos` (id 10, `status = true`) — **sem** recurso vinculado |

**Observação de contexto:** o changelog é, na prática, o **histórico do
produto** (vendas da empresa), não do sistema instalado na prefeitura.
A migration de seed traz entradas como "Public V6", "Gerar textos com
IA", "Reorganização dos Botões de Transparência Fiscal" — todas
funcionalidades do produto. Isso explica por que o módulo é interno e
por que não é filtrável por instalação.

---

## 4. Riscos de dados

| Risco | Detalhe | Mitigação |
|---|---|---|
| `deleted_at` nunca usado | exclusão já é definitiva; a coluna engana | aplicar `SoftDeletes` ou remover a coluna |
| `numero_versao` sem unicidade | 20+ entradas com "5.0" no seed | decidir o critério de unicidade (version + data) antes de aplicar |
| `title` sem limite no banco | `text` | a validação de servidor existe (`max:120`); ok |
| `icon` como texto livre | qualquer classe CSS pode ser injetada | lista fechada de ícones |
| `body` HTML não sanitizado | XSS no modal | sanitizar na escrita |
| `update_logs` x `change_logs` | o rodapé pode apontar para uma versão inexistente no changelog | unificar as tabelas ou criar um job de verificação |
| `ChangeLogTableSeeder` com `truncate` | apaga dados reais | tornar idempotente (`upsert` por título) |
| `UpdateLogs` com `description` no `$fillable` | erro em `fill()`/`create()` com esse campo | remover do `$fillable` |
| Imagens em `/storage/img/changelog/*.png` referenciadas por caminho absoluto no HTML | se o disk mudar, as imagens quebram | migrar para `Storage::disk('public')->url()` |

---

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

1. **O changelog deve ser público no portal?** Muitos portais
   apresentam "novidades" ao cidadão. Hoje é interno.
2. **Deve ser por instalação?** Hoje é global (do produto).
3. **A versão do rodapé e a do changelog devem ser a mesma fonte?**
   Recomenda-se unificar.
4. **A exclusão deve ser definitiva ou soft delete?**
5. **O ícone deve vir de uma lista fechada?**
6. **É preciso anexar documentos (release notes em PDF)?**
7. **Quem publica e quem aprova as novidades?** Não há campo de autor nem
   fluxo de aprovação.
8. **O número de versão deve ser único?** O seed mostra várias entradas
   com "5.0" — o que é correto (várias entregas na mesma versão), mas
   impõe um critério de unicidade diferente do simples `version`.

---

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

| Prioridade | Item | Arquivo |
|---|---|---|
| P0 | Remover a rota `changelog.show` (ou implementar o método) | `v6/routes/basepro.php:76` |
| P0 | Criar o recurso `changelog` (seeder idempotente) | novo seeder |
| P0 | Sanitizar título e descrição (HTML) | `v6/app/Http/Requests/ChangeLogRequest.php` + `changelog-modal.js` |
| P1 | Tratar a exceção do Carbon (validar a data no FormRequest) | `v6/app/Http/Controllers/Admin/ChangeLogController.php:47-52,88-93` |
| P1 | Validar `numero_versao` (formato e `max:20`) | `v6/app/Http/Requests/ChangeLogRequest.php` |
| P1 | Alinhar `maxlength` do título (150 -> 120) | `v6/resources/views/prefecture/configurations/changelog/form.blade.php` |
| P1 | Corrigir o HTML quebrado do `@if` na listagem | `v6/resources/views/prefecture/configurations/changelog/index.blade.php` |
| P1 | Trocar `str_limit` por `Str::limit` | `v6/resources/views/prefecture/configurations/changelog/index.blade.php:44,47` |
| P2 | Trocar `$dates` por `casts` | `v6/app/Http/Model/Admin/ChangeLog.php` |
| P2 | Declarar `protected $table` | `v6/app/Http/Model/Admin/ChangeLog.php` |
| P2 | Adicionar paginação e ordenar por `data_versao` | `v6/app/Http/Controllers/Admin/ChangeLogController.php:16` |
| P2 | Aplicar `SoftDeletes` (ou remover `deleted_at`) | `v6/app/Http/Model/Admin/ChangeLog.php` |
| P2 | Guardar `$modulos['novidades']` no menu | `v6/resources/views/vendor/adminlte/page.blade.php:310` |
| P2 | Registrar auditoria (`activity()`) | `v6/app/Http/Controllers/Admin/ChangeLogController.php` |
| P2 | Unificar `change_logs` e `update_logs` | nova migration |
| P3 | Remover `description` do `$fillable` de `UpdateLogs` | `v6/app/Http/Model/Prefecture/UpdateLogs.php:11-19` |
| P3 | Validar o formato da versão em `UpdateVersion` | `v6/app/Console/Commands/UpdateVersion.php:47-50` |
| P3 | Tornar o `ChangeLogTableSeeder` idempotente | `v6/database/seeds/ChangeLogTableSeeder.php` |
| P3 | Corrigir a indentação da migration de alteração | `v6/database/migrations/2025_09_26_103213_alter_number_versao_to_string_in_change_logs_table.php` |
