# P1.S6 — fechamento: E2E das jornadas, gates 2× e documentação

| Campo | Valor |
|---|---|
| **Fase** | P1 — Estrutura geral do site e do CMS |
| **Issue** | P1.S6 — provar as jornadas E2E (tema, shell, menus), rodar `make check` 2× + `E2E=1` e fechar a documentação |
| **`kd` task** | `task_01n7sbfw` (épico `epic_01vhakc0`) |
| **Âncoras** | `wiki/implementation-phases/P1-estrutura-site-cms.md` §3/S6, §5–§8 · `wiki/implementation-phases/TECNICO.md` §11/§14 · `_to_revision/PROTOCOLO.md` · ADR-001, ADR-016, ADR-022, ADR-025, ADR-036, ADR-046 |
| **Status da revisão** | ✅ revisado |

## O que foi implementado

- **Spec E2E novo** `src/tests-e2e/tests/18-estrutura-site.spec.ts` (projeto `cms-desktop`,
  `test.describe.serial`, 4 testes):
  - **Tema:** abre `Configurações → Aparência`, lê o `color_primary` efetivo, salva um `oklch()`
    válido, prova que `GET /theme.css` contém o token e muda de `ETag`, e que o portal referencia
    a folha e publica `--tenant-primary` em `getComputedStyle(...)`; restaura o valor original no
    `finally` e prova que o temporário sumiu do CSS.
  - **Shell:** muda `sidebar_position` para o lado oposto ao atual, prova
    `html[data-cms-sidebar]` e a **ordem de foco** (sidebar × `main#cms-content`); restaura e
    reafirma o atributo original.
  - **Menu (edição):** edita só o rótulo `pt_BR` do primeiro item do menu `principal`, prova o
    texto no `<nav aria-label="Menu principal">` do portal e restaura o rótulo original.
  - **Menu (remoção):** adiciona um item temporário com rota viva (`portal.home`) nas quatro
    locales, prova no header do portal, remove pela UI e exige **200** no redirect de volta
    (nunca 500), com o item ausente da tabela e do portal; limpeza defensiva no `finally`.
  - **Axe** (WCAG 2.0/2.1/2.2 A/AA) em Aparência, Painel, lista/árvore/edição de item e no portal
    no estado alterado.
  - Determinismo: sem espera fixa; o portal é aberto com chave de cache única por estado (o HTML
    público tem `max-age=300`, ADR-022) — a asserção espera o efeito, nunca o relógio.
- **Regressão de integração corrigida** em `17-cms-configuracoes.spec.ts`: o teste que exigia
  **404** em `/configuracoes/theme` passou a exigir o **editor real** de Aparência (200, `<h1>`,
  campo de token, axe) e mantém um 404 para seção desconhecida (`/configuracoes/desconhecida`).
- **Wiring de projeto:** `18-estrutura-site` entrou no `testMatch` de `cms-desktop` e no
  `testIgnore` de `portal-desktop`/`portal-mobile` (sem projeto novo; o contador do `AGENTS.md`
  continua 5).
- **Documentação:**
  - `histories/18-estrutura-site.md` (jornada, critérios, pré-condições, invariantes, fora de
    escopo, evidência) + índices em `src/tests-e2e/README.md` e `wiki/specs/04-acessibilidade-ux.md`.
  - `AGENTS.md`: “over 18 histories” (derivado do glob pelo `E2eDocsTest`).
  - Fichas `_to_revision/P1-S6.md` (esta) e `_to_revision/P1-estrutura-site-cms.md` (fase).
  - Fila `_to_revision/README.md`, estado em `wiki/implementation-phases/{README,P1-estrutura-site-cms}.md`
    e `INVENTARIO.md` com os itens entregues marcados `FEITO` **sem** declarar revisão.

## Fora desta fatia (não implementado de propósito)

- Nenhum produto novo: sem rota, campo, tabela ou permissão. Só prova, correção de teste
  desatualizado e documentação.
- Revisão profunda da fase (D1–D14) e aceite humano: ficam para a fila aberta por esta ficha.
- `theme.cms`/`theme.widgets`, logo por `media_id` e página (`page`) continuam nos limites
  registrados nas fichas S1–S5.

## Arquivos para revisar

- `src/tests-e2e/tests/18-estrutura-site.spec.ts` (novo)
- `src/tests-e2e/tests/17-cms-configuracoes.spec.ts` (regressão do 404 de `theme`)
- `src/tests-e2e/playwright.config.ts` (projetos, sem projeto novo)
- `src/tests-e2e/histories/18-estrutura-site.md` (novo) e `17-configuracoes-cms.md`
- `src/tests-e2e/README.md`
- `wiki/specs/04-acessibilidade-ux.md` (índice das histórias)
- `AGENTS.md` (contagem derivada de histórias)
- `_to_revision/P1-S6.md`, `_to_revision/P1-estrutura-site-cms.md`, `_to_revision/README.md`
- `wiki/implementation-phases/P1-estrutura-site-cms.md`, `wiki/implementation-phases/README.md`,
  `wiki/implementation-phases/INVENTARIO.md`

## Pontos de revisão

### D1 — Simplicidade / PHP 8.4
- [ ] Esta fatia não altera PHP de domínio; a spec usa helpers locais (`themeStylesheet`,
      `openPortal`, `focusOrder`) sem abstração compartilhada prematura.
- [ ] Nenhum helper novo em `support/` — os helpers existentes (`signIn`, `expectNoA11yViolations`)
      são reutilizados.

### D2 — Laravel 12
- [ ] Nenhuma rota/controller/request novo; as rotas exercitadas já existiam (S2–S4).

### D3 — Determinismo
- [ ] Sem `waitForTimeout`: as esperas são por URL/atributo/alerta/resposta.
- [ ] Estado restaurado no `finally` de cada teste (tema, posição, rótulo, item temporário).
- [ ] Portal aberto com chave de cache única por estado (HTML público `max-age`), sem depender de
      ordem entre arquivos (`fullyParallel: false` + 4 workers por arquivo).
- [ ] `make check` 2× e `make check E2E=1` verdes (números na evidência).

### D4 — Fronteiras
- [ ] A spec só fala HTTP (UI do painel + portal); não importa código PHP nem acessa banco.
- [ ] `cms-desktop` continua sendo o único projeto das telas do painel; portal assertado por
      página no mesmo contexto de browser (domínio isolado, ADR-037).

### D5 — Dependências / licenças / CDN
- [ ] Nenhuma dependência nova; `@axe-core/playwright`/`playwright` já pinados.
- [ ] O teste não introduz requisição externa (só same-origin portal/CMS).

### D6/D7 — CSS, HTML e a11y
- [ ] Axe A/AA em todas as telas tocadas e no portal no estado alterado.
- [ ] A prova de posição usa a ordem de foco (DOM), não pixels: `left` = sidebar antes do
      conteúdo, `right` = conteúdo antes da sidebar.
- [ ] Nenhum `style=`/`<style>`/`<script>` inline é criado ou exigido pela jornada.

### D8 — i18n
- [ ] Rótulos e mensagens da jornada vêm do locale `pt-BR` (contexto do projeto); o item
      temporário preenche as quatro locales, como o editor exige.
- [ ] Nenhuma string visível hardcoded em produto; textos do teste são dados de teste.

### D9/D10 — Grep-friendly / dados
- [ ] Spec/história seguem o prefixo numérico `18-` (`E2eDocsTest` 1:1).
- [ ] Nenhuma migração/tabela nova; a jornada usa o `principal` de referência e cria/remove só um
      item temporário.

### D11 — Segurança / LGPD
- [ ] Login pela UI (sessão nativa); nenhum segredo novo em fixture.
- [ ] Nenhum dado pessoal: rótulos e cores são conteúdo institucional.
- [ ] A remoção de item é `DELETE` com CSRF pela UI e exige 200 (nunca 500).

### D12 — Observabilidade / auditoria
- [ ] As mutações exercitadas continuam auditadas (`core.settings.updated`, `menus.*`); a spec não
      acrescenta evento nem log.
- [ ] Nenhum valor de token/rótulo vai para log da aplicação.

### D13 — Testes
- [ ] 4 testes novos; suíte E2E completa executa 118 testes (117 passed + 1 skip condicional) no
      projeto real, sem retry.
- [ ] Gates completos 2× + `E2E=1`; números na evidência abaixo.
- [ ] `git diff --check` limpo e `tools/docs-check.sh` verde.

### D14 — Documentação
- [ ] Histórias/specs/índices coerentes (`E2eDocsTest`); fichas S6 e da fase; fila e estado `🟡`.
- [ ] `INVENTARIO.md` marca os itens P1 entregues como `FEITO` e **não** afirma revisão.

## Evidência

- Spec dirigido (`E2E_WORKERS=1 tools/e2e.sh test 18-estrutura-site`): **4 passed** (25,1 s;
  wall 28,6 s), incluindo axe nas telas e no portal.
- Suíte E2E completa isolada (`tools/e2e.sh test`, 4 workers): **117 passed · 1 skipped** (118
  testes; 1,3 min; o skip é condicional pré-existente de `07-cms-shell`).
- `make check` **#1**: **22 OK · 0 FAIL · 11 SKIP**, **104,49 s**; `coverage` 892 testes /
  14.581 asserções; cobertura `src/` **92,87%**; `a11y` sniff estrito verde (28 `warn` de
  “transparent background” do `/cms/login`, já na ledger).
- `make check` **#2**: **22 OK · 0 FAIL · 11 SKIP**, **103,44 s**; mesmos 892/14.581 e 92,87%.
- `make check E2E=1`: **24 OK · 0 FAIL · 9 SKIP**, **197,91 s**; `e2e` **OK** em 84 s com
  **117 passed · 1 skipped** (história 18 incluída, sem retry), `a11y` 12 s e `perf` 6 passed.
- `git diff --check` limpo; `bash tools/docs-check.sh` → **OK** (13 specs com dono/status/link).
- Causa de um falso 403 na primeira execução local: perfil de demonstração semeado antes do módulo
  `Menus`; `php artisan db:seed --force` atualizou `menus.ver/editar` (documentado na história).

## Riscos e observações

- **Estado de dev após o e2e**: a restauração grava os valores efetivos originais (tema/posição),
  então uma linha válida passa a existir em `core_settings` mesmo quando antes só havia
  `config/`. O comportamento observável é o mesmo (o portal já referencia `/theme.css` com os
  tokens default; o shell mantém a posição original) e é o mesmo padrão da história 17. Não há
  reset “herdar default” na UI.
- **Concorrência entre arquivos**: o spec muda settings globais por poucos segundos. O portal tem
  `max-age=300`, e o shell é lido por request; a suíte completa rodou com 4 workers sem flake.
  Se o crescimento da suíte aumentar a janela, isolar a jornada em projeto próprio é a saída
  (hoje custaria um 6º projeto e o contador do `AGENTS.md`).
- **Pré-condição de demo**: o perfil `Administrador` deriva permissões do manifesto; um `db:seed`
  antigo não tem `menus.ver/editar`. A história documenta rodar o seed de novo (foi a causa de um
  falso 403 na primeira execução local).
- **`theme.css` no portal**: depois do primeiro save, o portal referencia a folha mesmo com
  valores iguais aos defaults. O orçamento de folhas do `11-performance` já prevê no máximo uma
  `theme.css`; nenhuma regressão medida.

## Notas da revisão

| Data | Revisor | Resultado | Observações |
|---|---|---|---|
| | | | |
