## Goal

Eliminar o uso de caminhos `'/storage/...'` hardcoded no portal público, substituindo pelo helper padrão `v2_storage_url()` (views) e `StorageService::url()` (models/services), conforme regra do projeto.

**Evidências (grep em 2026-08-17):**
- Models retornando URL crua:
  - `V2/Modules/Publicacoes/Agenda/Models/Evento.php:187` → `return '/storage/' . $image->file_path;` (método `getImageUrl()` usado em `Views/portal/index.blade.php:115` e no Schema.org do show).
  - `V2/Modules/Publicacoes/Noticias/Models/News.php:210` → `return '/storage/' . $this->coverImage->file_path;` (cover do portal).
- Views portal com path cru:
  - `V2/Modules/Publicacoes/Noticias/Views/portal/show.blade.php:53` → `contentUrl => url('/storage/' . $galleryMedia->file_path)` (JSON-LD).
  - `V2/Modules/Publicacoes/Noticias/Views/portal/show.blade.php:327` → `'src' => '/storage/' . $m->file_path`.
  - `V2/Modules/Institucional/AssocieSe/Views/portal/index.blade.php:61` → `$imgUrl = '/storage/' . $firstMedia->file_path;`.
- Views CMS (secundário — podem ficar para uma segunda passada se escopo apertar):
  - `AssocieSe/Views/cms/plans/edit.blade.php:52,54`; `TrabalheConosco/Views/cms/openings/_form.blade.php:53,66`; `Noticias/Views/cms/includes/_editor-content.blade.php:324,366`; `preview-iframe.blade.php:223`; scripts JS de gallery (`gallery-loader`, `detail-manager`, `upload-handler`).
- Controllers (metadados SEO — avaliar):
  - `NoticiasCmsController.php:240,391` → `$metadata['seo']['image_url'] = '/storage/' . ...` (armazenar path relativo no metadado pode ser OK; mas a exposição pública deve usar o helper).

**Solução esperada:**
1. **Models** (portal): `Evento::getImageUrl()` e `News` cover devem retornar via `StorageService::url()` (o serviço usado pelo helper) — manter a assinatura (retorno `?string`).
2. **Views portal**: substituir `url('/storage/...')`/`'/storage/...'` por `v2_storage_url(...)`.
3. **Caminho relativo vs absoluto**: o helper `v2_storage_url()` resolve o caminho absoluto (inclui domínio/cdn) — verificar que o `StorageService::url()` está acessível via DI no model (sem acoplar ao container diretamente, usar `app(StorageService::class)->url(...)` se necessário, seguindo padrão já usado no projeto).
4. **CMS/JS gallery**: se no escopo, aplicar o mesmo helper nas views blade CMS; nos scripts JS, manter padrão existente (o upload handler já monta `/storage/` — avaliar se o CMS roda com disk local; deixar como segunda passada se não houver tempo).
5. Revalidar com SniffCSS/curl que as imagens continuam carregando (200) nas páginas tocadas.

## Non-Goal

- Não migrar dados/arquivos de storage (nada muda no armazenamento físico).
- Não alterar o helper `v2_storage_url()` nem `StorageService`.
- Não renomear colunas/relações de imagem.
- Não mexer nos seeders (dados SLE com paths inline em rich content são geridos pelo editor — fora do escopo, salvo se forem views).

## Constraints

PHP 7.4 | PHPUnit ~6.0. Nunca commitar. Model: UUID, SoftDeletes.
Use o X-CMS-AI-Token do ai_acess definido no .env para ter livre acesso ao CMS a nível de UI/UX
SniffCSS habilitado em MCP e Host para consulta da página real
Docker only. execute via docker compose exec app [command]
Regra: `v2_storage_url()` em views, `StorageService::url()` em controllers/services quando necessário.
Composer usa classmap-authoritative: rodar `composer dump-autoload` após adicionar classes novas (se houver).

## Success Criteria

1. Grep final: nenhum `'/storage/'` ou `url('/storage/...')` hardcoded nas views portal (`V2/layouts/portal`, `V2/Modules/*/Views/portal`) e nos models usados pelo portal (`Evento`, `News`).
2. Imagens das páginas tocadas (agenda index/show, notícia show, associe-se index) carregam com URL resolvida corretamente (curl 200 no src final).
3. SniffCSS não mostra regressão visual (imagens exibidas nas mesmas posições).
4. Testes existentes dos módulos tocados continuam passando; suíte V2 Unit não regride.
5. (Opcional) Teste unit novo: `getImageUrl()` retorna URL via StorageService (mock).

================================================================================

# RESULT-LOG

```
Status: Concluído
Date: 2026-08-17
Sub-tasks: 3/3 (models, views, testes)
Files modified: 4 (Evento.php, AssocieSe index, Noticias show x2)
Seeds closed: 1/1 (sucesu-edcc)
Outcome: '/storage/' hardcoded eliminado dos models e views portal. Código agora
         usa StorageService::url() (models) e v2_storage_url() (views).
Notes:
  - Evento::getImageUrl() agora usa app(StorageService::class)->url($path).
  - AssocieSe index: $imgUrl = v2_storage_url($firstMedia->file_path).
  - Noticias show: contentUrl e src da galeria usam v2_storage_url().
  - News.php: try já usa StorageService; fallback no catch mantido (rede segurança).
  - CMS views e JS gallery fora do escopo (decisão do plano: segunda passada).
  - Testes: tests/Unit/V2/Modules/Publicacoes/StorageUrlTest.php (2 testes, 4 asserts)
    — Evento::getImageUrl() usa StorageService e retorna null sem imagem.
  - Imagens continuam com formato /storage/ porque o disk é local; o ponto é que
    o código agora é flexível (service, não hardcoded).
```

================================================================================

# AI-AREA

```
1. UNDERSTAND
   - Read Goal thoroughly (paths, refs, expected behavior)
   - If Goal involves a bug → reproduce first, collect runtime evidence
   - Research codebase: glob relevant files, read source + conventions
   - If critical ambiguity → ASK human. Minor → ASSUME + document.

2. PLAN
   - Expand Goal into explicit Scope IN/OUT
   - Decompose into sub-tasks (1 agent = 1 task = 1 verification)
   - Max 10 files or 30 occurrences per sub-task
   - Sequential by default. Parallel only if independent.
   - Register: sd create → sd plan create → sd plan adopt → sd sync

3. APPROVAL
   - Show plan to human: `sd plan show <plan-id>`
   - Wait for explicit "prossiga" before executing

4. EXECUTE
   - For each sub-task sequentially:
     a. Delegate to coder via task tool
     b. Verify against Success Criteria
     c. IF implementation involves UI, verify with SniffCSS (MCP || CLI command)
     d. IF fail any verify → correction sub-task, repeat 4a
     e. sd close <seed-id> --reason "[result]"

5. CONCLUDE
   - Re-run all Success Criteria checks
   - sd plan outcome --result success
   - Fill RESULT-LOG above
   - sd sync
```