# PLATAFORMA — Dependências, Acoplamentos e Riscos

> Continuação de `05-REGRAS-E-PORTABILIDADE.md`. Ver também `05-REGRAS-E-PORTABILIDADE.md`.

## 3. Dependências de composer abandonadas

Versões travadas em `v6/composer.lock` (idênticas na v5 — nenhum upgrade
dependência aconteceu entre as versões).

### 3.1 Pacotes com risco de migração

| Pacote | Versão | Status | Impacto na v7 |
|---|---|---|---|
| `cartalyst/sentinel` | `2.0.18` | **Abandonado** (2017) | Autenticação + permissões. Substituir por **Sanctum + Policies**. Afeta **todo** o CMS. |
| `laravelcollective/html` | `5.5.4` | **Abandonado** | Facade `HTML::` (37 usos em Blades). No Laravel 11+, usar `Illuminate\Support\HtmlString` e o componente `<x-...>`. |
| `jadjoubran/laravel-angular` | `0.3.0` | **Abandonado** (AngularJS 1.x, EOL em 2022) | CMS carrega AngularJS. Exige reescrita dos formulários do CMS. |
| `phaza/laravel-postgis` | `3.3.2` | **Não mantenido** para Laravel moderno | Declarado, mas **nenhuma coluna geometry foi encontrada**. Pode ser removido, mantendo o driver `pgsql` + `postgis` na extensão. |
| `swiftmailer/swiftmailer` | `6.3.0` | **Abandonado** (dez/2021) | E-mail. Migrar para **Symfony Mailer** (nativo do Laravel 9+). |
| `fzaninotto/faker` | `1.9.2` | **Abandonado** (autor removido do Packagist) | `require-dev`; substituir por `fakerphp/faker`. |
| `guzzlehttp/guzzle` | `5.3.4` | **EOL desde 2015** (5.x) | HTTP client. Migrar para `guzzlehttp/guzzle ^7.9`. |
| `doctrine/dbal` | `2.13.9` | Versão 2.x EOL; 3.x/4.x exigem PHP 8.1+ | Depende de `yajra/laravel-datatables` 1.x. Atualizar ambos. |
| `yajra/laravel-datatables` | `1.5.0` | **Superado** pela v2 (Laravel 9+) | Tabelas do CMS. Atualizar para `^2.0` ou reescrever. |
| `barryvdh/laravel-dompdf` | `0.8.7` | Versão antiga; `^3.0` é a atual | PDF. Atualizar. |
| `dompdf/dompdf` | `0.8.6` | Idem | — |
| `tecnickcom/tcpdf` | `6.11.4` | Ainda mantido, mas com APIs deprecated no PHP 8.2+ | PDF do diário. |
| `intervention/image` | `2.7.2` | v2 EOL; v3 reescreveu a API | Imagens (galeria, banners, webp). Atualizar para `^3.0` — **API breaking**. |
| `laracasts/presenter` | `0.2.9` | Não mantido | 10 presenters. Substituir por **API Resources** ou **Value Objects**. |
| `laracasts/flash` | `3.0.3` | **Abandonado** | `flash('…')->success()` em todo o CMS. Substituir por **session flash** nativo. |
| `laralabs/toaster` | `2.0.1` | Não mantido | Notificações. Substituir por componente Vue/Toast do stack novo. |
| `jeroennoten/laravel-adminlte` | `1.22.0` | v1 EOL; v3 é o atual | Layout do CMS. Avaliar manter (v3) ou reescrever. |
| `spatie/laravel-activitylog` | `2.8.4` | v2 para Laravel 5; v4 atual | Log de atividades. Atualizar. |
| `simplesoftwareio/simple-qrcode` | `2.0.0` | v2 EOL; v4 atual | QR Code. |
| `laravellegends/pt-br-validator` | `5.2.1` | Fork não mantido oficialmente | Validações pt-BR. Substituir por `laravel-lang/pt-br` ou regras próprias. |
| `canducci/zipcode` | `1.1` | Não mantido | Busca de CEP. Substituir por API dos Correios. |
| `blueimp/jquery-file-upload` | `9.34.0` | jQuery plugin legado | Upload múltiplo — migrar para `Dropzone` ou `Filament`-style upload. |
| `greggilbert/recaptcha` | `2.2.0` | Não mantido | reCAPTCHA. |
| `fideloper/proxy` | `3.3.4` | Substituído por `fideloper/proxy` v4 | — |
| `rosell-dk/webp-convert` | `1.3.9` | Não mantido | WebP. |
| `setasign/fpdi` | `2.6.9` | Ainda mantido | FPDF/TCPDF. |
| `blueimp` / `laravel/tinker` / `filp/whoops` | — | `tinker` ~1.0 e `whoops` ~2.0 são **EOL** | Tinker do Laravel 5; migrar para `^2.10`. |

### 3.2 O que **não** migrou entre v5 e v6

`v5/composer.json` e `v6/composer.json` são **praticamente idênticos** nas
dependências. A única diferença estrutural é o autoload:

| Item | v5 | v6 |
|---|---|---|
| `composer.json` deps | 34 `require` + 5 `require-dev` | 35 `require` + 6 `require-dev` |
| Diferença | — | `yajra/laravel-datatables ^1.5` e `barryvdh/laravel-dompdf` presentes na v6; `phpunit/phpunit ~6.0` e `mockery` mantidos |
| `davejamesmiller` → `diglactic` | **Corrigido** (ver `dossie_modules/_01_v5_fix/README.md`) | Já era `diglactic` |

**Conclusão:** a v6 **não modernizou nenhuma dependência**. Todo o trabalho
de atualização de stack é 100% dívida da v7.

---

## 4. Acoplamentos estruturais

### 4.1 O módulo é a chave da permissão

O eixo de autorização do CMS é o par **(slug do módulo, nome da rota)**:

```
resources.slug  →  modulos.id  →  menu_orders.modulo_id
```

- `resources` (79 linhas) tem `modulo_id` FK para `modulos`.
- `menu_orders` (45 linhas) tem `modulo_id` FK para `modulos`.
- `modulos.status` liga/desliga o módulo **inteiro** na sidebar.

A consequência: **desligar um módulo (`status = false`) remove o item do menu
e nenhuma rota morre** — as rotas continuam registradas e acessíveis se o
usuário souber a URL e tiver a permissão. A segurança real depende
exclusivamente do `CheckRoutePermission`.

### 4.2 Autorização por nome de rota

`v6/app/Http/Middleware/CheckRoutePermission.php` resolve a permissão a
partir do **nome** da rota, com três listas de exceção:

```php
$resourceRoutes = [
    'edit' => 'update',
    'create' => 'store',
    'delete' => 'destroy',
];
$openRoutes = [
    'login', 'logout', 'datatable', 'dashboard', 'error', 'ajax', 'info-request-status-update'
];
```

E ainda tem 3 blocos `if` hardcoded para casos especiais
(`responder_chamado`, `enviar_resposta`, `diario-config.*`,
`refresh-PDF*`, `diario.generation-status`).

**Fragilidade:** renomear uma rota = mudar a permissão. Adicionar uma rota
nova = criar um nome novo = **sem permissão por padrão** (o que é seguro),
mas o inverso — criar rota com nome já existente — **concede acesso**.

### 4.3 Leitura de dados pelo nome da view

`v6/app/Http/Controllers/Prefecture/DatatableController.php` monta as
DataTables lendo **views SQL** como tabelas:

```php
public function get_noticias()
{
    $noticias = DB::table('noticias')->get();
    return DataTables::of($this->struct_views($noticias, 'noticias'))->make(true);
}
```

São ~40 métodos `get_*` nesse padrão. Isso amarra o CMS ao **formato exato**
das views: renomear uma coluna na view quebra a tela.

### 4.4 Layout como configuração de conteúdo

O campo `section` da tabela `layouts` decide **quais notícias** aparecem no
carrossel (`v6/app/Http/Traits/NewsTrait.php:178`). Layout ≠ apresentação
pura.

### 4.5 `Configuration` como chave/valor universal

A tabela `configurations` guarda **todas** as configurações do portal
(`layout`, `noticias`, `pagina_em_manutencao`, `active_landing`,
`menu_interativo`, cores `cor_1`…). Acesso **direto e não cacheado** a cada
requisição (`Configuration::where('key', …)->first()`).

### 4.6 Código duplicado v5 → v6

- `getTemplateActived()`: `v6/app/Http/Traits/GetInformationsPrefectureTrait.php:92`
  **e** `v6/app/Http/Controllers/Admin/Controller.php:39`.
- `formatValidationErrors()`: `v6/app/Http/Controllers/Admin/Controller.php`
  **e** `v6/app/Http/Controllers/Prefecture/Controller.php`.
- `v6/app/Http/Model/Admin/Person.php` e `v6/app/Http/Model/Admin/Person.php.orig`
  (arquivo `.orig` **versionado** no repositório).
- `v6/resources/views/admin/user_new/` e `v6/resources/views/admin/user_new_views/`
  — duas árvores de views de usuário **idênticas** (comparação por conteúdo
  mostra os mesmos `<select>` e `data-placeholder`).

---

## 5. Riscos de migração

### 5.1 Views SQL

| Risco | Detalhe | Mitigação v7 |
|---|---|---|
| 75 views dropadas se o schema for recriado | As views **não** são versionadas como código de aplicação, mas como migrations | Recriar as 75 views em migrations idempotentes da v7, ou convertê-las em **Query Objects**/Eloquent scopes |
| Colunas de presentation dentro da view (`status_name`, `data_publicacao`) | O CMS e o portal consomem esses nomes | Manter os nomes ou mapear explicitamente no Resource |
| `row_number() OVER (…)` como `value` | A ordenação manual de widgets depende do valor | Fixar a ordenação em `order` explícito |
| Acoplamento do `DatatableController` ao formato da view | 40+ telas | Substituir por Resources + DataTables server-side tipado |
| `CREATE OR REPLACE VIEW` com dependência de outra view | Alterar a ordem de migration quebra | Manter ordem cronológica ou recriar na ordem de dependência |

### 5.2 Colunas geometry / PostGIS

**Risco real: BAIXO.** Nenhuma coluna `geometry` foi encontrada (grep por
`geometry|postgis` em `v6/database/migrations` → 0 arquivos). O pacote
`phaza/laravel-postgis` está declarado, mas o PostGIS é usado apenas como
**extensão do PostgreSQL**. A v7 só precisa garantir que a extensão
`postgis` esteja instalada no Postgres de destino (mesmo que o Laravel não
a use nativamente).

### 5.3 Arquivos em disco

| Local | Conteúdo | Risco |
|---|---|---|
| `v6/public/storage` / `v6/storage/app/public` | Galeria de arquivos, anexos de conteúdo, arquivos de conteúdo | Referenciados por `archives.path` (string relativa) — **migração exige reindexar os caminhos** |
| `v6/storage/app/…` | PDFs gerados (diário oficial, carta de serviços) | `service_letter_pdfs`, `diario_oficial_pdf` guardam caminho em disco |
| `v6/public/swagger.yml` | Documentação gerada | Regenerar |
| `v6/public/assets/` | 2.026 `.js` + CSS + fontes + imagens | Artefatos **não versionados como pipeline**; precisam de migração para o build da v7 |

**Ponto crítico:** as colunas de caminho (`archives.path`,
`service_letter_pdfs.path`, etc.) são strings livres. A v7 deve normalizar
para `Storage::disk('public')` com nomes determinísticos e um **serviço de
migração de arquivos**.

### 5.4 Sequences e IDs

Todas as PKs são `serial` (`nextval`). Ao recriar o schema, os valores de
`id` mudam e **quebram**: URLs com id hardcoded, arquivos com nome contendo
id (`diario-oficial/content/{id}/images`), referências em `menu_orders` e
`resources`.

**Mitigação:** a v7 deve **preservar os IDs** (migração de dados com
`INSERT ... SELECT` mantendo a PK explícita) ou adoptar **UUID/ULID** com
mapa de conversão.

### 5.5 `created_at`/`updated_at` são `timestamp(0)`

Sem fuso horário (`without time zone`) e com **precisão de segundos**.
O código usa `Carbon::parse()` em pontos-chave. Na v7, migrar para
`timestamptz` com microsegundos exige revisar todos os
`to_char(... 'DD/MM/YYYY')` das views (75 views!) e as comparações de
período.

### 5.6 Sessão e cache

- Sessão: driver `file` (`.env.example`: `SESSION_DRIVER=file`); Sentinel
  guarda a sessão em `persistences` (tabela) com a chave `cartalyst_sentinel`.
- Cache: `file` no `.env.example`, mas `ModulosServiceProvider` usa
  `Cache::rememberForever('modulos', …)` — **cache não invalidado** quando o
  status de um módulo muda. Alterar `modulos.status` só tem efeito após
  `cache:clear`.

---

## 6. Regras de negócio implícitas (transversais)

1. **Slug é a chave de todo o portal.** `category_contents.slug` filtra as
   views; `contents.slug` gera as URLs (`/noticia/{slug}`,
   `/transparencia/{slug}`, `/publicacoes/{slug1}/{slug2}`).
2. **Soft delete em quase tudo** (86 de 131 models). As views filtram
   `deleted_at IS NULL` explicitamente — mas **nem todas**. Uma view sem
   esse filtro expõe conteúdo removido.
3. **`clicks` é incrementado** a cada acesso (`updateClicks()` no trait) —
   é o "mais lidas" do portal.
4. **`status` booleano** marca publicado/rascunho; `highlights` marca
   destaque; `carousel` marca participação no carrossel; `order` a ordenação
   manual.
5. **`publication_date` no futuro** esconde o conteúdo do portal (trait
   `byPublication()`), mas pode ser visível no CMS.
6. **`layout = <modelo>` sem `home/index`** → **o portal inteiro entra em
   manutenção**.
7. **`resources` + `modulos`** definem o que o operador vê; desligar o
   módulo não desliga a rota.
8. **Layout `section = 'tags'`** troca o critério do carrossel de destaque
   para o mais recente.

---

## 7. Referências

| Item | Caminho |
|---|---|
| Autorização por nome de rota | `v6/app/Http/Middleware/CheckRoutePermission.php` |
| Login do CMS | `v6/app/Http/Middleware/CheckLogged.php` |
| Manutenção do portal | `v6/app/Http/Middleware/CheckSiteManutention.php` |
| Landing page | `v6/app/Http/Middleware/ActiveLanding.php` |
| Repositório base com `dd()` | `v6/app/Repositories/Repository.php` |
| Leitura de views como tabelas | `v6/app/Http/Controllers/Prefecture/DatatableController.php` |
| Cache de módulos | `v6/app/Providers/ModulosServiceProvider.php` |
| Dependências | `v6/composer.json`, `v6/composer.lock` |
| Correção da dependência de breadcrumb na v5 | `dossie_modules/_01_v5_fix/README.md` |
| Configuração de views/breadcrumbs | `v6/config/breadcrumbs.php` |
