# Verificação das reconstruções cegas — C1 `MOD-INFRAESTRUTURA-MAILAUDIT` e C2 `MOD-INFRAESTRUTURA-FEEDRSS`

## 1. Método

- **Entradas comparadas.** `mailaudit.md` = `_qa/blind/mailaudit.md` (raiz do workspace); `feedrss.md` = `sucesu_analise/_qa/blind/feedrss.md`. `sucesu-cms/V2/...` é o código real (gabarito); `05_modulos/...`, `02_servicos-base/...`, `01_arquitetura/...`, `08_matriz/...` e `_indices/...` são o corpus, relativos a `sucesu_analise/`.
- **Protocolo.** Aplicação de `09_reimplementacao/reconstrucoes-cegas.md` §§P4–P6: comparação por chave (tabela+coluna; método+URI; rota+DOM/campo; PC; efeito observável), classes `DV-A` a `DV-E` e severidade `S1` a `S3`. O gabarito veio do código (controllers, blades, services, models, migrations, middlewares), não do `spec.md`.
- **Execução.** Comparação estática, sem subir a aplicação, sem banco e sem rodar testes; nenhuma escrita em `V2/`, docs de unidade ou artefatos cegos. As únicas execuções foram leitura de arquivos e `grep`.
- **Normalização.** Middleware comparado por efeito, não por ordem textual; respostas comparadas por código HTTP e mensagem literal quando o corpus a fixa; telas comparadas por campos/DOM/eventos, não por classes CSS. Para `Collection::where` foi conferida a implementação do Laravel 5.5 (`composer.json:15`; `vendor/laravel/framework/src/Illuminate/Support/Collection.php:459-495`).
- **Limite.** Não há banco disponível para provar o `500` do id não-UUID; a conclusão vem do tipo `uuid` no PostgreSQL e de `find($id)` em `FeedRssService.php:182`, e está marcada como `[INFERENCE]` onde for o caso.

## 2. Isolamento

Não encontrei indício de violação da regra de isolamento.

- Todos os detalhes exatos dos dois artefatos têm lastro no corpus: por exemplo, o DDL de `v2_mail_logs` (`05_modulos/Infraestrutura/MailAudit/spec.md:455-474`), o DDL de `v2_feed_rss_items` (`05_modulos/Infraestrutura/FeedRss/spec.md:496-538`), o `isSupportUser()` (`FeedRss/spec.md:206-219`), o literal `enabled === '1'` (`FeedRss/spec.md:229-231`), as mensagens de flash (`FeedRss/spec.md:64-76`), a cadeia de middlewares (`01_arquitetura/04-middlewares-seguranca.md:242-250`) e os índices parciais.
- Onde o artefato errou, ele errou **contra** o código e **a favor** de uma leitura do corpus: a coluna “Data” da listagem (`mailaudit.md:237`) usa `sent_at ?? created_at`, mas o código usa só `created_at` (`index.blade.php:171`); “Módulo” da tabela usa `ucfirst` (`feedrss.md:262`), mas o código usa o valor cru (`index.blade.php:117`). Um agente com acesso ao código teria acertado os dois.
- O artefato **não** reproduziu detalhes que só estão no código: formato `d/m/Y H:i:s` do detalhe (`mailaudit.md:289` deixa como `BL-MAILAUDIT-07`), rótulos “Enviado”/“Falha” (`mailaudit.md:240` deixa como `BL-MAILAUDIT-03`), `setTitle('Feed RSS — Suporte')` (`feedrss.md:531` deixa como `BL-FEEDRSS-06`). Isso é evidência de que o código não foi visto.
- O único detalhe “de repositório” citado — a existência de `MailAudit/README.md` (`mailaudit.md:496`) — está no corpus em `00_inventario/manifest.json:195` e `01_arquitetura/10-grupos-e-modulos-vazios.md:288`, não é conhecimento privilegiado.

Conclusão: o isolamento parece ter sido respeitado. As divergências abaixo são de **suficiência/ambiguidade do corpus** ou de **inferência do reconstruidor**, não de acesso ao código.

## 3. Tabela de divergências

> `mailaudit.md` e `feedrss.md` são os artefatos cegos; `spec.md` é o doc da unidade. Código relativo a `sucesu-cms/`.

| ID | unidade | classificação DV | severidade | artefato cego | código real | causa | correção |
|---|---|---|---|---|---|---|---|
| C1-01 | MailAudit | **DV-B** | S2 | `mailaudit.md:237,289,373`: coluna “Data” = `sent_at ?? created_at` | `Views/cms/index.blade.php:171` usa só `created_at`; o fallback `sent_at ?? created_at` existe apenas no detalhe (`detail.blade.php:61`) | **Ambiguidade do corpus**: `spec.md:468` diz “`sent_at` … data exibida (fallback `created_at`)” sem separar lista e detalhe; `spec.md:544` só fixa o formato `d/m/Y H:i` | Corrigir `spec.md`: lista = `created_at`; detalhe = `sent_at ?? created_at`; ajustar o artefato para a lista |
| C1-02 | MailAudit | **DV-B** | S2 | `mailaudit.md:163,178-179,337`: “`none`/chave ausente bloqueia” sem exceção | `V2/Core/Middleware/V2PermissionMiddleware.php:69-72` libera e-mail de suporte e `super-admin` antes do RBAC; `V2/Core/Services/PermissionService.php:46-49` repete o bypass em `v2_can` | **Erro/omissão do corpus da unidade**: `spec.md:586,618` e §10.2 não qualificam “perfil comum”; o doc transversal tem a regra (`01_arquitetura/03-auth-rbac-sentinel.md:455`, RN-CORE-AUTH-03) | Qualificar as linhas de `none` em `spec.md:586,618` e no artefato: suporte/super-admin com `none` recebem `200`; somente perfil comum recebe `302/403` |
| C1-03 | MailAudit | **DV-D** | S1 | `mailaudit.md:45,155,180-181,542` (BL-01) escolhe `404` e registra o conflito | `V2/Core/Middleware/ModuleAccessMiddleware.php:46-62`: prefixo `cms/mail-audit` não é `cms`, logo `abort(404, 'Modulo desativado.')`; AJAX `404` JSON | **Erro do corpus**: `spec.md:621` afirma `302` + flash; o artefato seguiu a regra transversal e acertou o código | Corrigir `spec.md:621` (e a linha equivalente de §1.3) para `404 Modulo desativado.`; manter o artefato |
| C1-04 | MailAudit | **DV-D** | S3 | `mailaudit.md:503-513`: “configuração do provider (valor exato)” sem `icon` do submenu e sem `subModulesLevel2` | `ModuleProvider.php:24` tem `'icon' => 'bi bi-clock-history'`; `:27` tem `'subModulesLevel2' => []` | **Erro do corpus**: `spec.md:597-609` omite os dois campos, mas o artefato os chama de “valor exato” | Adicionar os dois campos em `spec.md:597-609` ou remover a palavra “exato”; ajustar o artefato |
| C1-05 | MailAudit | **DV-D** | S2 | `mailaudit.md:35,262,386`: “comparação exata; qualquer outro valor zera a lista” | `MailAuditCmsController.php:52-54`: `if (!empty($status))` + `Collection::where('status', $status)`; `Collection.php:491-494` compara com `==` (não `===`); `empty('0') === true` | **Erro do corpus**: `spec.md:72` e `:298` prometem comparação exata e “qualquer outro valor zera”; `?status=0` é tratado como ausente e devolve a listagem normal (até 50), não vazio (PHP 7.2) | Corrigir `spec.md:72,298`: documentar `!empty` (o literal `'0'` não filtra) e que `where` é comparação frouxa; o artefato deve registrar o caso `'0'` |
| C2-01 | FeedRss | **DV-A** | S3 | `feedrss.md:262`: célula “Módulo” da tabela com `ucfirst($item->module)` | `Views/cms/index.blade.php:117` imprime `$item->module` cru; `ucfirst` só existe na distribuição por módulo (`:72`) | **Lacuna do corpus**: `spec.md:584` lista a coluna “Módulo”, mas não diz que a tabela usa o valor cru nem que só a distribuição usa `ucfirst` | Corrigir `spec.md:584`/§8.1 e o artefato: tabela = `$item->module`; distribuição = `ucfirst($module)` |
| C2-02 | FeedRss | **DV-A** | S2 | `feedrss.md:531` (BL-06) e §4.1: nenhum título de página; `SEOService` só citado como injeção | `FeedRssSupportController.php:66` chama `$this->seo->setTitle('Feed RSS — Suporte')`; a blade define `'title' => 'Feed RSS'` (`Views/cms/index.blade.php:1`) | **Lacuna do corpus**: `spec.md:574-590` não fixa título de página nem o `setTitle` do controller; o artefato marcou a injeção como possível dependência morta | Documentar em `spec.md` o título `Feed RSS` e o `setTitle('Feed RSS — Suporte')`; remover a hipótese de “dependência morta” |
| C2-03 | FeedRss | **DV-D** | S1 | `feedrss.md:526` (BL-01) escolhe `404` e registra o conflito | `ModuleAccessMiddleware.php:46-62`: prefixo `cms/v2/feed-rss` ≠ `cms` → `abort(404, 'Modulo desativado.')`; o índice parcial já registra `404` | **Erro do corpus**: `spec.md:77` afirma `302` + flash, citando `ModuleAccessMiddleware.php:46-59` (que na verdade cai no `abort`) | Corrigir `spec.md:77` e §11 para `404 Modulo desativado.`; o índice está certo; manter o artefato |
| C2-04 | FeedRss | **DV-C** | S3 | `feedrss.md:534` (BL-09): “grafia da flag não define case-sensitivity” | `V2/Core/Services/ModuleFlagService.php:72-94` tenta chave exata, `strtolower` e `pascalToSnake`; ausência = ativo | **Erro do reconstruidor**: o corpus já documenta o fallback em `01_arquitetura/03-auth-rbac-sentinel.md:436-437` e `01_arquitetura/04-middlewares-seguranca.md:245-246` | Não alterar o corpus por causa deste BL; calibrar o prompt e, se útil, acrescentar cross-reference em `spec.md:10.3` |
| C2-05 | FeedRss | **DV-B** | S2 | `feedrss.md:527` (BL-02): “não está claro se o bypass ocorre antes do match” | `V2PermissionMiddleware.php:69-72`: o bypass de suporte/super-admin vem depois do match e antes da permissão; `01_arquitetura/03-auth-rbac-sentinel.md:455` fixa RN-CORE-AUTH-03 | **Ambiguidade do corpus da unidade**: `spec.md:615` diz “com perfil `FeedRss=none` o middleware bloqueia” sem excluir suporte/super-admin; o doc transversal resolve | Qualificar `spec.md:615`: “perfil comum”; suporte/super-admin com `none` acessa; fechar `BL-FEEDRSS-02` |
| C2-06 | FeedRss | **DV-B** | S3 | `feedrss.md:538` (BL-13): “não há exemplo para `deleteItem`” | `FeedRssService.php:207-225` (`deleteItem`) audita com o próprio item; `:79-93` (`removeItem`) audita com `new FeedRssItem()` (sujeito vazio) | **Ambiguidade do corpus**: `spec.md:651` diz “sujeito = item (já soft-deleted)” para “Remover”; `02_servicos-base/feed-rss.md:521` diz “a remoção usa sujeito vazio”, referindo-se a `removeItem` | Disambiguar em `spec.md:651` e `02_servicos-base/feed-rss.md:521`: `deleteItem` = item; `removeItem` = sujeito vazio |
| C2-07 | FeedRss | **DV-A** | S1 | `feedrss.md:529` (BL-04): `{id}` não-UUID “pode gerar 500”, sem contrato | `FeedRssService.php:182` faz `FeedRssItem::find($id)`; a coluna é `uuid` e o PostgreSQL rejeita texto inválido (`invalid input syntax for type uuid`) → `QueryException`/500 `[INFERENCE]` | **Lacuna do corpus**: nenhum doc fixa o comportamento para `{id}` fora de UUID; a rota não tem `where()` (`Routes/cms.php:15-23`) | Documentar a decisão em `spec.md` §3.3/§5: validar com `whereUuid` e responder “Item não encontrado.”, ou registrar o `500` como contrato legado |
| C2-09 | FeedRss | **DV-A** | S3 | `feedrss.md:263`: coluna “Tipo” com `$item->entity_type` “cru” | `Views/cms/index.blade.php:118` renderiza `<code>{{ $item->entity_type }}</code>` | **Lacuna do corpus**: `spec.md:584` não fixa o markup da célula | Documentar o `<code>` em `spec.md:584`; ajustar o artefato |
| C2-10 | FeedRss | **DV-A** | S3 | `feedrss.md:252-258` não registra o vazio da distribuição nem o título da página | `Views/cms/index.blade.php:76-78`: “Nenhum item cadastrado.”; `:1`: `'title' => 'Feed RSS'` | **Lacuna do corpus**: `spec.md:574-590` só fixa o vazio da tabela e não fixa o vazio da distribuição nem o título | Acrescentar os dois estados/textos em `spec.md:574-590` |

### 3.1 DV-E (índices)

Não encontrei divergência nova de índice que exija correção. As tabelas de `_indices/parcial-SVC-MAILSERVICE/tabelas.csv` e `_indices/parcial-SVC-FEEDRSS/tabelas.csv` conferem com as migrations. Em `_indices/parcial-MOD-INFRAESTRUTURA-FEEDRSS/rotas.csv`, a resposta “404 módulo desativado” confere com o código; a divergência está no `spec.md:77` (DV-D), não no índice. O `componentes.csv` do FeedRss lista `$stats` sem `last_item`, mas a view não consome essa chave; não há efeito observável.

## 4. Lacunas do corpus reveladas pelo exercício

A tabela abaixo consolida o que o corpus ainda não fecha. “Artefato” indica se o erro foi percebido (`BL-*`) ou não. Severidade conforme o protocolo.

| ID | unidade | lacuna/erro | severidade | artefato | correção no corpus |
|---|---|---|---|---|---|
| L-C1-01 | MailAudit | Resposta de módulo desativado: `302` no doc × `404` no código | **S1** | percebido (`BL-MAILAUDIT-01`) e resolvido para `404` | `spec.md:621` e §1.3: trocar por `404 Modulo desativado.` |
| L-C1-02 | MailAudit | Bypass de suporte/super-admin no RBAC não aparece na matriz da unidade | **S2** (S1 se lido como autorização) | não percebido | `spec.md:586,618`/§10.2: qualificar “perfil comum”; citar `V2PermissionMiddleware.php:69-72` |
| L-C1-03 | MailAudit | Origem da data da listagem (`created_at`) vs detalhe (`sent_at` com fallback) | S2 | não percebido (inferiu `sent_at`) | `spec.md:468,544`: separar lista e detalhe |
| L-C1-04 | MailAudit | `status=0` é engolido por `!empty('0')`; `where` é `==`, não `===` | S2 | parcialmente (`BL-05` cita `0` só para busca) | `spec.md:72,298`: documentar `!empty` e comparação frouxa |
| L-C1-05 | MailAudit | Fórmula da “Taxa de Sucesso” (`round(...,1)`, `0` quando total 0) | S2 | percebido (`BL-02`) | `spec.md:534-552`: fixar a fórmula e o estado zero |
| L-C1-06 | MailAudit | Rótulos de status/profile e placeholder da busca | S2 | percebido (`BL-03/04/05`) | `spec.md:534-552`: “Todos os status”, “Enviado”, “Com falha”, “Todos”, “default”, placeholder |
| L-C1-07 | MailAudit | Formato do detalhe (`d/m/Y H:i:s`), título “Auditoria de E-mails”/“Detalhes do Envio”, breadcrumb do detalhe | S3 | percebido (`BL-07/09`) | `spec.md:534-573`: fixar |
| L-C1-08 | MailAudit | Fallback de `from_address` nulo: o código renderiza o HTML escapado literalmente (`<span ...>Não informado</span>`) | S3 | percebido parcialmente (`BL-11`) | `spec.md:554-573`: documentar o fallback e o bug de escape; decidir se a reimplementação reproduz |
| L-C1-09 | MailAudit | Contagem “X registro(s) exibido(s)” e `title` do badge `failed` (`Erro desconhecido`) | S3 | não percebido | `spec.md:534-552`: acrescentar |
| L-C1-10 | MailAudit | Desempate de `created_at` idêntico | S3 | percebido (`BL-10`) | `spec.md:534-552`: documentar que não há segunda chave |
| L-C1-11 | MailAudit | Retenção/mascaramento de PII e a exposição integral do corpo | S2 | percebido (`BL-13`) | decisão de produto/segurança; `spec.md` §13 |
| L-C2-01 | FeedRss | Módulo desativado: `302` no doc × `404` no código | **S1** | percebido (`BL-FEEDRSS-01`) e resolvido para `404` | `spec.md:77` e §11: trocar por `404 Modulo desativado.` |
| L-C2-02 | FeedRss | `{id}` não-UUID: `500` do PostgreSQL | **S1** | percebido (`BL-04`) | `spec.md` §3.3/§5: decidir validação ou documentar o `500` |
| L-C2-03 | FeedRss | Republicação após soft delete: unique violation sem filtro `deleted_at` | **S1** | percebido (`BL-11`) | decisão explícita (reproduzir a falha ou unique parcial/delete físico) em `spec.md` §3.4 e `feed-rss.md` §3.4 |
| L-C2-04 | FeedRss | `setTitle('Feed RSS — Suporte')` e título da página | S2 | percebido (`BL-06`), mas sem o conteúdo | `spec.md` §2.2/§8.1: documentar |
| L-C2-05 | FeedRss | Célula “Módulo” da tabela usa valor cru, não `ucfirst` | S3 | não percebido | `spec.md:584`: documentar |
| L-C2-06 | FeedRss | RBAC × identidade: `none` bloqueia só perfil comum; suporte/super-admin bypassam | S2 | percebido (`BL-02`), resolução correta | `spec.md:615`: qualificar e fechar BL-02 |
| L-C2-07 | FeedRss | CSRF: status/corpo/mensagem de `419` não documentados | S2 | percebido (`BL-05`) | `spec.md` §3/§11: documentar o 419 do framework |
| L-C2-08 | FeedRss | Campos fixos do RSS, `logoUrl`, `language`, `description` e `published_at = null` em `toRssString()` | S2 | percebido (`BL-08`) | `02_servicos-base/feed-rss.md` §3.3/§5: fixar; decidir o caso nulo |
| L-C2-09 | FeedRss | Sujeito da auditoria: `deleteItem` usa o item; `removeItem` usa sujeito vazio | S3 | percebido (`BL-13`), mas a redação do BL é ambígua | disambiguar `spec.md:651` e `feed-rss.md:521` |
| L-C2-10 | FeedRss | Atomicidade entre `UPDATE` e `INSERT` de auditoria | S2 | percebido (`BL-14`) | `spec.md` §11/`feed-rss.md` §9: documentar ausência de transação e o efeito |
| L-C2-11 | FeedRss | `v2.support.email` vazio/nulo | S2 | percebido (`BL-18`) | `spec.md` §10.1: fixar o comportamento de `!empty` |
| L-C2-12 | FeedRss | `deleteItem` em item já soft-deleted | S2 | percebido (`BL-10`) | `spec.md` §3.2: documentar `find` + `false` |
| L-C2-13 | FeedRss | Ordem dos badges de módulo (`groupBy` sem `orderBy`) | S3 | percebido (`BL-12`) | `spec.md` §8.1: documentar ordem indefinida |
| L-C2-14 | FeedRss | Paginação fora de faixa (`?page=999`) e headers do painel | S3 | percebido (`BL-15/17`) | `spec.md` §8.1/§11: documentar |
| L-C2-15 | FeedRss | Ausência de testes do painel/toggle/delete | S2 | percebido (`BL-16`) | registrar em `spec.md` §13 e criar testes na reimplementação |
| L-C2-17 | FeedRss | `<code>` na coluna “Tipo” e vazio “Nenhum item cadastrado.” | S3 | não percebido | `spec.md` §8.1: acrescentar |

### 4.1 Lacunas declaradas que o corpus já fecha

- `BL-FEEDRSS-09` (grafia da flag): o corpus documenta o fallback `isActive` em `01_arquitetura/03-auth-rbac-sentinel.md:436-437` e `01_arquitetura/04-middlewares-seguranca.md:245-246`; o código confirma (`ModuleFlagService.php:72-94`). **DV-C**, S3; não alterar o corpus.
- `BL-FEEDRSS-02` (ordem do bypass): o doc transversal fixa o bypass de suporte/super-admin após o match (`01_arquitetura/03-auth-rbac-sentinel.md:455`; `V2PermissionMiddleware.php:69-72`). A lacuna real é só a redação de `spec.md:615`; o artefato já implementou o comportamento certo.

## 5. Veredito por unidade

### C1 — `MOD-INFRAESTRUTURA-MAILAUDIT`: **suficiente com ressalvas**

- **Schema:** 14/14 colunas, tipos, defaults, índices, UUID, soft delete e ausência de FK/unique conferem com a migration (`2026_06_30_000000_create_v2_mail_logs_table.php:27-67`).
- **Rotas:** 2/2 métodos, URIs, nomes, controller/ação, `web` + `module.active:MailAudit` + `CmsAuthenticate` conferem (`Routes/cms.php:18-19`; `V2ServiceProvider.php:303-307`). O único desvio é a matriz de permissão (C1-02), não a rota.
- **Telas:** a estrutura, os 4 cartões, os filtros, a tabela, o detalhe, o corpo escapado, os estados vazios e as mensagens principais estão corretos. A coluna “Data” é o erro material (C1-01); rótulos/fórmula/formatos ficaram como `BL-*` (S2/S3).
- **Regras/fluxos:** o bug central (`getHistory(1)` + `firstWhere`), o universo 200/corte 50, os filtros, as estatísticas globais, a ausência de escrita/cache/auditoria e o soft delete estão corretos.
- **Ressalvas:** C1-01 (S2), C1-02 (S2), C1-05 (S2) e C1-04 (S3). Pelo critério do protocolo §5, C1 teria **3 S2 abertas** se a matriz de autorização for contada como S2; o limiar é ≤2. A estrutura central é reconstruível, mas o corpus precisa das correções L-C1-01..L-C1-04 antes de uma segunda rodada passar o gate.

### C2 — `MOD-INFRAESTRUTURA-FEEDRSS`: **suficiente com ressalvas**

- **Schema:** o módulo não tem schema próprio; o DDL de `v2_feed_rss_items`, o unique sem filtro de `deleted_at`, o UUID no `creating`, os casts e os escopos conferem (`2026_07_20_000001_create_v2_feed_rss_items_table.php:27-48`; `FeedRssItem.php:31-149`).
- **Rotas:** 3/3 métodos, URIs, nomes, controller/ação, CSRF/method spoofing e a cadeia `web` → `module.active:FeedRss` → `CmsAuthenticate` → `V2PermissionMiddleware` conferem (`Routes/cms.php:5-24`; `V2ServiceProvider.php:303-307`). O `404` do módulo desativado está correto no artefato.
- **Telas:** a página, os 4 cartões, a distribuição, a tabela paginada, os formulários, o `confirm()` e o rodapé estão corretos. Faltam o `setTitle` (C2-02), a célula “Módulo” crua (C2-01), o `<code>` de “Tipo” (C2-09) e o vazio da distribuição (C2-10).
- **Regras/fluxos:** `enabled === '1'`, soft delete, auditoria, cache de 5 min sem invalidação, `getStats`, `paginate(20)`, `isSupportUser`, `restricted` e o UPSERT que reabilita estão corretos.
- **Ressalvas:** C2-02 (S2), C2-01 (S3), C2-09/10 (S3) e os `BL-02/09/13`. O corpus tem **S1 abertos** (não-UUID e republicação) e um `302` errado no doc; o artefato resolveu o `302` e sinalizou os S1. Depois das correções L-C2-01..L-C2-03, a unidade deve passar.

## 6. Correções priorizadas no corpus (não aplicadas)

**P0 — status/segurança (bloqueiam o gate):**

1. `05_modulos/Infraestrutura/MailAudit/spec.md:621` e §1.3: trocar `302` + flash por `404 Modulo desativado.`; mesma correção em `05_modulos/Infraestrutura/FeedRss/spec.md:77` e §11. Evidência: `ModuleAccessMiddleware.php:46-62`.
2. `MailAudit/spec.md:586,618` e `FeedRss/spec.md:615`: qualificar o RBAC — `none` bloqueia **perfil comum**; e-mail de suporte e `super-admin` bypassam. Evidência: `V2PermissionMiddleware.php:69-72`; `PermissionService.php:46-49`; `01_arquitetura/03-auth-rbac-sentinel.md:455`.
3. `FeedRss/spec.md` §3.3/§5: fixar o comportamento de `{id}` não-UUID (validar e responder “Item não encontrado.” ou registrar o `500` legado). Evidência: `FeedRssService.php:182`; `Routes/cms.php:15-23`.
4. `FeedRss/spec.md` §3.4: decisão explícita sobre a republicação de item soft-deleted (reproduzir a unique violation ou unique parcial/delete físico). Evidência: migration `:42-44`; `FeedRssService.php:42-59`.

**P1 — contrato observável (segunda rodada):**

5. `MailAudit/spec.md:468,544`: lista usa `created_at`; detalhe usa `sent_at ?? created_at`.
6. `MailAudit/spec.md:72,298`: documentar `!empty`/`==` e o caso `?status=0`.
7. `MailAudit/spec.md:534-552` e `:597-609`: fórmula da taxa (`round(...,1)`, zero), rótulos/placeholder e o `icon`/`subModulesLevel2` do provider.
8. `FeedRss/spec.md:584` e §8.1: célula “Módulo” crua, `<code>` em “Tipo”, título `Feed RSS`, `setTitle('Feed RSS — Suporte')` e o vazio “Nenhum item cadastrado.”.
9. `FeedRss/spec.md` §11 e `02_servicos-base/feed-rss.md:521`: separar `deleteItem` (sujeito = item) de `removeItem` (sujeito vazio).
10. `FeedRss/spec.md` §3/§9/§11: CSRF `419`, atomicidade da auditoria, `v2.support.email` vazio e `deleteItem` já soft-deleted.

**P2 — completude de tela/contrato:**

11. `MailAudit/spec.md:534-573`: formatos `d/m/Y H:i:s`, breadcrumb do detalhe, fallback de `from_address` (incluindo o escape literal do HTML), contagem “X registro(s) exibido(s)” e `title` do badge `failed`.
12. `FeedRss/spec.md` §8.1/§11: ordem dos badges, paginação fora de faixa, headers do painel.
13. `FeedRss/spec.md` §13: registrar a ausência de testes e prescrever os testes de contrato (o artefato já os lista em §6.1).

**P3 — calibração do exercício:**

14. Não alterar o corpus por `BL-FEEDRSS-09`; registrar como DV-C e ajustar o prompt para consultar `01_arquitetura/03-auth-rbac-sentinel.md` e `04-middlewares-seguranca.md` antes de declarar lacuna de flag.
15. Na segunda rodada, usar agentes novos e congelar os artefatos; comparar novamente as colunas Schema/Rotas/Telas/PCs e os S1/S2.
