docs: reconciliar a stack declarada do site público com a implementação (#35)

Conclusão da auditoria pedida na MAN-117.

A pergunta da issue era se "Vue + Livewire" faz sentido na arquitetura
atual. Vue não aparece em lugar nenhum: não está no package.json, não há
nenhum arquivo .vue, e a própria SPEC §11.3 já proibia framework SPA.
Metade da premissa da issue não tem base no repositório.

Livewire existe, mas não onde a SPEC dizia. O pacote entra apenas como
dependência transitiva de filament/support e opera somente dentro do
painel /admin. O site público é Blade renderizado no servidor mais JS
vanilla progressivo: o layouts.public carrega apenas
@vite(['resources/css/app.css', 'resources/js/app.js']), sem
@livewireScripts, e não há uma única diretiva wire: ou x-data em
resources/views. Alpine só existe empacotado dentro do runtime do
Livewire, duas indireções abaixo do Filament — nunca chega a uma página
pública.

Mesmo assim, cinco lugares afirmavam o contrário: §0 metadados, §5.3,
§9.1, §11 inteira e a ADR-002, que está marcada como Aceita descrevendo
uma arquitetura que a área que ela nomeia não implementa.

A correção adota o que existe em vez de construir o que estava
declarado. O motivo é o próprio documento: a §11.2 já registrava
Blade + Controller como resultado aceito, os requisitos que a §11.2 pede
do formulário (loading state, botão desabilitado, aria-busy) já são
atendidos por resources/js/app.js, e nada nas Fases 2 a 5 pede
reatividade no site público. Adotar Livewire agora colocaria um bundle
global de JS e CSS em páginas cujo resultado visual está fixado por
baselines de snapshot, a serviço de um requisito que ninguém escreveu.

Como a §0.2 proíbe alterar silenciosamente uma decisão do documento, a
correção não reescreve a ADR-002 fingindo que ela sempre disse outra
coisa: o texto dela é emendado apontando para uma ADR-015 nova, que
registra a decisão explicitamente. E a §22 ganha uma linha nomeando a
condição objetiva que justificaria reabrir o assunto — a mesma que a
§11.1 já previa em prosa, "se houver necessidade de consulta dinâmica".

Fica de fora deste commit, para evitar conflito com trabalho em curso no
mesmo arquivo: a linha equivalente em openspec/config.yaml, que também
carrega uma afirmação desatualizada sobre a cidade de atuação e será
corrigida de uma vez só.

Co-Authored-By: Claude noreply@anthropic.com
AI-Assisted: yes
AI-Tool: claude-code

Co-authored-by: manoel.neto <manoel.neto@creditas.com>
This commit is contained in:
2026-08-10 08:58:42 -03:00
committed by GitHub
parent 54cd6ba0da
commit 2e2860396e

37
SPEC.md
View File

@@ -20,7 +20,7 @@
| Princípio principal | YAGNI — implementar somente o necessário para validar o produto | | Princípio principal | YAGNI — implementar somente o necessário para validar o produto |
| Arquitetura | Monólito modular Laravel | | Arquitetura | Monólito modular Laravel |
| Área interna | Filament | | Área interna | Filament |
| Área pública | Livewire + Blade | | Área pública | Blade + JS vanilla progressivo (Livewire é dependência do Filament, não usada no site público — ver ADR-015) |
| Servidor de aplicação | FrankenPHP em modo regular | | Servidor de aplicação | FrankenPHP em modo regular |
| Banco de dados | PostgreSQL | | Banco de dados | PostgreSQL |
| Testes | Pest, Pest Browser/Playwright e testes visuais | | Testes | Pest, Pest Browser/Playwright e testes visuais |
@@ -315,8 +315,8 @@ Administração
- Dashboard: `Filament Page` customizada com widgets orientados a exceção. - Dashboard: `Filament Page` customizada com widgets orientados a exceção.
- Detalhe do evento: página customizada do Resource com resumo operacional. - Detalhe do evento: página customizada do Resource com resumo operacional.
- Briefing público: componente Livewire próprio. - Briefing público: Blade + Controller (`POST /contato`), ver §11.2.
- Home: Blade/Livewire com componentes de design reutilizáveis. - Home: Blade com componentes de design reutilizáveis.
### 5.4 Decisões de UX YAGNI ### 5.4 Decisões de UX YAGNI
@@ -1553,7 +1553,7 @@ Constraints de banco devem proteger:
| Runtime | PHP com versão minor fixada no Docker | | Runtime | PHP com versão minor fixada no Docker |
| Framework | Laravel 13 | | Framework | Laravel 13 |
| Admin | Filament 5 | | Admin | Filament 5 |
| UI pública | Livewire 4 + Blade + Alpine + Tailwind | | UI pública | Blade + Tailwind + JS vanilla progressivo (sem framework reativo; Livewire 4 confinado ao Filament — ver ADR-015 e §22) |
| Banco | PostgreSQL | | Banco | PostgreSQL |
| Servidor | FrankenPHP + Caddy | | Servidor | FrankenPHP + Caddy |
| Assets | Vite | | Assets | Vite |
@@ -1774,21 +1774,21 @@ Usar componentes/Widgets menores e testáveis.
--- ---
## 11. Livewire e site público ## 11. Site público e interatividade
### 11.1 Componentes sugeridos ### 11.1 Estado atual e componentes candidatos
- `ContactBriefingForm`; O site público **não usa Livewire nem Alpine hoje**. As páginas são Blade renderizado no servidor mais JavaScript vanilla progressivo (`resources/js/app.js` e `resources/js/motion.js`). O `layouts.public` carrega apenas `@vite(['resources/css/app.css', 'resources/js/app.js'])` — nenhum `@livewireScripts`. O pacote `livewire/livewire` existe no projeto apenas como dependência transitiva de `filament/support` e opera somente dentro do painel `/admin`.
- `FeaturedPortfolioCases` se houver necessidade de consulta dinâmica;
- `PublishedServices` se houver necessidade de consulta dinâmica.
Não transformar todas as seções estáticas em componentes Livewire. Usar Blade quando não houver estado ou interação. Se surgir a necessidade de consulta dinâmica, os candidatos naturais a Livewire seriam `FeaturedPortfolioCases` e `PublishedServices`. Essa adoção está condicionada ao gatilho registrado em §22.
Não transformar seções estáticas em componentes Livewire. Usar Blade quando não houver estado ou interação.
### 11.2 Formulário de briefing ### 11.2 Formulário de briefing
> **Estado atual (Fases 01):** o formulário é implementado em Blade + Controller (`POST /contato`, `ContactBriefingRequest`), conforme WEB-05. Se a Fase 2 mantiver Blade + Controller, os requisitos abaixo valem para o formulário e seus testes independentemente da tecnologia; a criação de Lead segue para a Fase 2. > **Estado atual:** o formulário é implementado em Blade + Controller (`POST /contato`, `ContactBriefingRequest`), conforme WEB-05, e essa é a abordagem aceita — não um estágio provisório. Os requisitos abaixo valem independentemente da tecnologia; a criação de Lead segue para a Fase 2.
O componente deve: O formulário deve:
- ter estado tipado ou Form Object quando útil; - ter estado tipado ou Form Object quando útil;
- validar no servidor; - validar no servidor;
@@ -1797,15 +1797,16 @@ O componente deve:
- preservar acessibilidade; - preservar acessibilidade;
- limpar dados após sucesso; - limpar dados após sucesso;
- evitar exposição de exceção; - evitar exposição de exceção;
- suportar teste Livewire sem browser; - suportar teste de submissão sem navegador (feature test);
- suportar jornada E2E em navegador real. - suportar jornada E2E em navegador real.
### 11.3 JavaScript ### 11.3 JavaScript
- usar Alpine apenas para interações pequenas; - manter o site público em JS vanilla progressivo;
- não introduzir framework SPA; - não introduzir framework SPA;
- não usar dependência JS quando CSS/HTML/Livewire resolverem; - não usar dependência JS quando CSS e HTML resolverem;
- toda interação crítica deve funcionar sem estado global complexo. - toda interação crítica deve funcionar sem estado global complexo;
- Alpine só entra junto com Livewire, se o gatilho de §22 disparar.
--- ---
@@ -2500,7 +2501,7 @@ Toda operação financeira deve:
| ADR | Decisão | Status | | ADR | Decisão | Status |
|---|---|---| |---|---|---|
| ADR-001 | Monólito modular Laravel, sem microserviços | Aceita | | ADR-001 | Monólito modular Laravel, sem microserviços | Aceita |
| ADR-002 | Filament para área interna e Livewire/Blade para área pública | Aceita | | ADR-002 | Filament para área interna (Livewire é dependência interna do Filament); site público em Blade — ver ADR-015 | Aceita |
| ADR-003 | PostgreSQL como único banco transacional | Aceita | | ADR-003 | PostgreSQL como único banco transacional | Aceita |
| ADR-004 | Pagamentos somente manuais | Aceita | | ADR-004 | Pagamentos somente manuais | Aceita |
| ADR-005 | Pest unifica unit, feature, browser e visual | Aceita | | ADR-005 | Pest unifica unit, feature, browser e visual | Aceita |
@@ -2513,6 +2514,7 @@ Toda operação financeira deve:
| ADR-012 | E-mail transacional via Resend (mailer nativo Laravel) | Aceita | | ADR-012 | E-mail transacional via Resend (mailer nativo Laravel) | Aceita |
| ADR-013 | Design system Heritage Editorial para o site público | Aceita | | ADR-013 | Design system Heritage Editorial para o site público | Aceita |
| ADR-014 | Deploy via Dokploy Compose com imagem imutável por SHA no GHCR | Aceita | | ADR-014 | Deploy via Dokploy Compose com imagem imutável por SHA no GHCR | Aceita |
| ADR-015 | Site público permanece Blade + JS vanilla; Livewire e Alpine ficam restritos ao Filament até o gatilho de §22. Emenda o texto da ADR-002 | Aceita |
--- ---
@@ -2529,6 +2531,7 @@ Toda operação financeira deve:
| API pública | existe consumidor real e contrato de integração | | API pública | existe consumidor real e contrato de integração |
| Kanban | tabela de leads demonstra limitação frequente observada | | Kanban | tabela de leads demonstra limitação frequente observada |
| Editor de checklist | diferentes tipos de evento exigem manutenção frequente do seed | | Editor de checklist | diferentes tipos de evento exigem manutenção frequente do seed |
| Livewire no site público | portfólio ou serviços exigem consulta ou filtro dinâmico que Blade + JS vanilla não resolvem de forma simples |
--- ---