docs: sync SPEC.md and openspec with ratified decisions

This commit is contained in:
2026-08-05 23:33:29 -03:00
parent 9fac784f6a
commit 018b43e24f
6 changed files with 73 additions and 41 deletions

104
SPEC.md
View File

@@ -14,7 +14,8 @@
| Estágio | MVP | | Estágio | MVP |
| Status da especificação | Aprovada para implementação | | Status da especificação | Aprovada para implementação |
| Idioma da interface | Português do Brasil (`pt-BR`) | | Idioma da interface | Português do Brasil (`pt-BR`) |
| Timezone padrão | `America/Fortaleza` | | Timezone padrão | `America/Sao_Paulo` |
| Cidade de atuação | São Paulo (capital) |
| Moeda | BRL, sem conversão entre moedas | | Moeda | BRL, sem conversão entre moedas |
| 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 |
@@ -44,6 +45,8 @@ Em caso de conflito, seguir esta ordem:
O agente **NÃO DEVE** alterar silenciosamente uma decisão deste documento. Uma alteração de escopo ou arquitetura deve atualizar esta especificação ou criar uma ADR. O agente **NÃO DEVE** alterar silenciosamente uma decisão deste documento. Uma alteração de escopo ou arquitetura deve atualizar esta especificação ou criar uma ADR.
Mudanças incrementais são planejadas em `openspec/changes/` e, após arquivadas, este documento DEVE ser revalidado para incorporar decisões ratificadas (back-sync). Este arquivo permanece a fonte de verdade do produto.
--- ---
## 1. Contrato de operação para agentes ## 1. Contrato de operação para agentes
@@ -349,13 +352,14 @@ A home DEVE conter, nesta ordem aproximada:
1. header e navegação; 1. header e navegação;
2. hero com proposta de valor e CTA; 2. hero com proposta de valor e CTA;
3. prova visual por eventos em destaque; 3. manifesto da marca;
4. resumo dos serviços; 4. resumo dos serviços em destaque;
5. método de trabalho; 5. casos selecionados do portfólio;
6. casos selecionados; 6. método de trabalho (4 passos);
7. depoimentos; 7. depoimentos;
8. CTA final para briefing; 8. posicionamento/perfil;
9. footer com contato, redes e links legais. 9. CTA final para briefing;
10. footer com contato, redes e links legais.
A ordem pode variar apenas se a revisão de UX justificar a mudança. A ordem pode variar apenas se a revisão de UX justificar a mudança.
@@ -374,6 +378,15 @@ Centralizar tokens de:
Não espalhar valores visuais arbitrários por componentes. Não espalhar valores visuais arbitrários por componentes.
O MVP adota o sistema de design **Heritage Editorial** (ver DESIGN.md e ADR-013):
- tipografia serifada auto-hospedada (EB Garamond) com escala de display a label;
- paleta papel/oliva/sálvia/tinta com superfícies tonais; hierarquia sem sombras de card;
- raio de borda zero para superfícies interativas e de conteúdo;
- largura de container 1120px e ritmo de espaçamento de 8px;
- `prefers-reduced-motion` respeitado;
- contraste WCAG AA (tinta sobre papel e oliva sobre papel).
### 6.4 Requisitos de mídia ### 6.4 Requisitos de mídia
- Imagens públicas DEVERÃO possuir texto alternativo. - Imagens públicas DEVERÃO possuir texto alternativo.
@@ -383,6 +396,7 @@ Não espalhar valores visuais arbitrários por componentes.
- Dimensões DEVERÃO ser reservadas para evitar layout shift. - Dimensões DEVERÃO ser reservadas para evitar layout shift.
- Não armazenar blobs de imagem no PostgreSQL. - Não armazenar blobs de imagem no PostgreSQL.
- Não depender do disco efêmero do contêiner em produção. - Não depender do disco efêmero do contêiner em produção.
- O logotipo da marca DEVE possuir texto alternativo e variantes claro/escuro; `site_settings.logo_path` sobrescreve o asset padrão quando preenchido.
### 6.5 Acessibilidade ### 6.5 Acessibilidade
@@ -534,12 +548,10 @@ Campos públicos:
- validar no servidor; - validar no servidor;
- usar honeypot e rate limiting; - usar honeypot e rate limiting;
- impedir duplo envio acidental; - impedir duplo envio acidental;
- criar Lead com status `new`;
- registrar origem `website`;
- notificar administradores;
- exibir sucesso sem revelar dados internos;
- enviar e-mail de confirmação quando o serviço de e-mail estiver configurado; - enviar e-mail de confirmação quando o serviço de e-mail estiver configurado;
- falha no e-mail não pode apagar o lead já criado. - exibir sucesso sem revelar dados internos.
> **Estado atual (Fases 01):** o formulário usa Blade + Controller e envia apenas e-mails informativos (para a assessoria e confirmação ao visitante), sem criar Lead. A criação de Lead (status `new`, origem `website`), a notificação aos administradores e o registro de aceite de privacidade entram na **Fase 2**, quando o formulário passa a criar o Lead via `CaptureWebsiteLead`. A falha de e-mail não pode apagar dados já criados.
**Aceite:** **Aceite:**
@@ -1253,10 +1265,19 @@ Singleton:
- `id` bigint PK; - `id` bigint PK;
- `brand_name`; - `brand_name`;
- `logo_path` nullable;
- `logo_alt` nullable;
- `hero_eyebrow` nullable; - `hero_eyebrow` nullable;
- `hero_title`; - `hero_title`;
- `hero_subtitle`; - `hero_subtitle`;
- `hero_cta_label`; - `hero_cta_label`;
- `hero_cta_secondary_label` nullable;
- `hero_note` nullable;
- `manifesto_title`;
- `manifesto_lead`;
- `manifesto_body`;
- `method_steps` jsonb (4 passos tipados);
- `principles` jsonb (lista tipada);
- `about_summary` nullable; - `about_summary` nullable;
- `email`; - `email`;
- `phone`; - `phone`;
@@ -1265,7 +1286,8 @@ Singleton:
- `default_meta_title`; - `default_meta_title`;
- `default_meta_description`; - `default_meta_description`;
- `default_og_image_path` nullable; - `default_og_image_path` nullable;
- analytics fields nullable; - `default_og_image_alt` nullable;
- `analytics_enabled` boolean default false;
- timestamps. - timestamps.
#### `services` #### `services`
@@ -1536,7 +1558,7 @@ Constraints de banco devem proteger:
| Servidor | FrankenPHP + Caddy | | Servidor | FrankenPHP + Caddy |
| Assets | Vite | | Assets | Vite |
| Testes | Pest 4 + Pest Browser/Playwright | | Testes | Pest 4 + Pest Browser/Playwright |
| Arquivos | Laravel Filesystem + storage S3-compatible em produção | | Arquivos | Laravel Filesystem + Cloudflare R2 (S3-compatible) em produção |
| Fila | Database queue | | Fila | Database queue |
| Scheduler | Laravel Scheduler em processo separado | | Scheduler | Laravel Scheduler em processo separado |
@@ -1764,6 +1786,8 @@ Não transformar todas as seções estáticas em componentes Livewire. Usar Blad
### 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.
O componente deve: O componente deve:
- ter estado tipado ou Form Object quando útil; - ter estado tipado ou Form Object quando útil;
@@ -1970,7 +1994,7 @@ Determinismo obrigatório:
- Chromium e imagem Linux fixos; - Chromium e imagem Linux fixos;
- viewport fixo; - viewport fixo;
- timezone `America/Fortaleza`; - timezone `America/Sao_Paulo`;
- locale `pt-BR`; - locale `pt-BR`;
- fontes instaladas na imagem; - fontes instaladas na imagem;
- relógio congelado; - relógio congelado;
@@ -2052,7 +2076,7 @@ quality → Pint check + PHPStan/Larastan + audits + testes
| Job | Responsabilidade | Bloqueia merge | | Job | Responsabilidade | Bloqueia merge |
|---|---|---:| |---|---|---:|
| `static` | Pint, PHPStan/Larastan, Composer validate e audits | Sim | | `static` | Pint, PHPStan/Larastan, Composer validate, Composer e npm audit | Sim |
| `unit` | Unitários, arquitetura e cobertura | Sim | | `unit` | Unitários, arquitetura e cobertura | Sim |
| `feature` | PostgreSQL, migrations, Livewire, Filament e integração | Sim | | `feature` | PostgreSQL, migrations, Livewire, Filament e integração | Sim |
| `browser` | Vite, FrankenPHP, E2E, smoke, acessibilidade e visual | Sim | | `browser` | Vite, FrankenPHP, E2E, smoke, acessibilidade e visual | Sim |
@@ -2073,11 +2097,11 @@ quality → Pint check + PHPStan/Larastan + audits + testes
### 14.3 Branches e ambientes ### 14.3 Branches e ambientes
- PR: testes e preview opcional; - PR: testes e preview opcional;
- `main`: build imutável por SHA e deploy automático em staging; - `main`: build imutável por SHA publicado no GHCR e deploy automático em staging via Dokploy;
- staging: migration, cache warmup e smoke pós-deploy; - staging: Dokploy Compose executa migração, healthcheck `/up` e smoke pós-deploy (`/up`, `/`, `/admin/login`);
- produção: promoção da mesma imagem aprovada, sem rebuild; - produção: promoção da mesma imagem aprovada, sem rebuild (retag do digest em `:production`);
- produção requer aprovação humana explícita no MVP; - produção requer aprovação humana explícita no MVP (`workflow_dispatch` com confirmação);
- rollback usa imagem anterior; - rollback usa imagem anterior (SHA anterior, sem rebuild);
- migrations devem ser backward-compatible quando possível. - migrations devem ser backward-compatible quando possível.
### 14.4 Definition of Done ### 14.4 Definition of Done
@@ -2159,7 +2183,7 @@ APP_DEBUG=false
APP_URL APP_URL
APP_LOCALE=pt_BR APP_LOCALE=pt_BR
APP_FALLBACK_LOCALE=pt_BR APP_FALLBACK_LOCALE=pt_BR
APP_TIMEZONE=America/Fortaleza APP_TIMEZONE=America/Sao_Paulo
DB_CONNECTION=pgsql DB_CONNECTION=pgsql
DB_HOST DB_HOST
@@ -2172,19 +2196,16 @@ CACHE_STORE=database ou file conforme ambiente
QUEUE_CONNECTION=database QUEUE_CONNECTION=database
SESSION_DRIVER=database ou cookie conforme decisão SESSION_DRIVER=database ou cookie conforme decisão
FILESYSTEM_DISK=s3 em produção FILESYSTEM_DISK=r2 em produção
AWS_ACCESS_KEY_ID R2_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY R2_SECRET_ACCESS_KEY
AWS_DEFAULT_REGION R2_BUCKET
AWS_BUCKET R2_ENDPOINT
AWS_ENDPOINT opcional R2_URL (domínio próprio opcional)
AWS_USE_PATH_STYLE_ENDPOINT opcional AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION, AWS_BUCKET, AWS_ENDPOINT, AWS_USE_PATH_STYLE_ENDPOINT opcionais, apenas se o disk s3 for usado
MAIL_MAILER MAIL_MAILER=resend em produção (mailer nativo Laravel)
MAIL_HOST RESEND_API_KEY
MAIL_PORT
MAIL_USERNAME
MAIL_PASSWORD
MAIL_FROM_ADDRESS MAIL_FROM_ADDRESS
MAIL_FROM_NAME MAIL_FROM_NAME
``` ```
@@ -2279,7 +2300,7 @@ O seed deve criar:
- configurações do site; - configurações do site;
- 3 serviços; - 3 serviços;
- 3 casos de portfólio; - 3 casos de portfólio;
- 3 depoimentos; - depoimentos reais: os 5 casais de `depoimentos.md` (Jeniffer e Maick, Quesia e Jhonata, Milena e Weslley, Raquel e Pedro, Victoria e Pedro), preservando texto e datas; autores fictícios de demonstração removidos; em produção permanecem não publicados até autorização explícita de publicação;
- leads em estados variados; - leads em estados variados;
- 2 eventos futuros e 1 concluído; - 2 eventos futuros e 1 concluído;
- tarefas vencidas e futuras; - tarefas vencidas e futuras;
@@ -2314,7 +2335,7 @@ O agente deve implementar na sequência, salvo instrução explícita.
- [x] Filament instalado e autenticado; - [x] Filament instalado e autenticado;
- [x] Livewire configurado; - [x] Livewire configurado;
- [x] Tailwind/Vite; - [x] Tailwind/Vite;
- [x] FrankenPHP e Docker Compose local; - [~] FrankenPHP e Docker Compose local (imagem pronta; serviço de aplicação local pendente);
- [x] papéis admin/assistant; - [x] papéis admin/assistant;
- [x] Pint; - [x] Pint;
- [x] PHPStan/Larastan; - [x] PHPStan/Larastan;
@@ -2325,6 +2346,13 @@ O agente deve implementar na sequência, salvo instrução explícita.
- [x] design tokens mínimos; - [x] design tokens mínimos;
- [x] healthcheck; - [x] healthcheck;
- [x] seed de admin local. - [x] seed de admin local.
- [ ] verificação de e-mail e reset seguro (MustVerifyEmail);
- [ ] npm audit no `composer quality` e no job `static`;
- [ ] gate de cobertura `Domain`/`Application` ≥ 80%;
- [ ] serviço de aplicação FrankenPHP no Compose local;
- [ ] hello-world implantado em staging (critério de saída).
> Os itens pendentes acima são tratados pela mudança OpenSpec `complete-foundation-parity`; o critério de saída da fase só é atingido com staging implantado.
**Critério de saída:** pipeline verde e hello-world implantado em staging. **Critério de saída:** pipeline verde e hello-world implantado em staging.
@@ -2481,6 +2509,10 @@ Toda operação financeira deve:
| ADR-008 | Database queue; Redis adiado | Aceita | | ADR-008 | Database queue; Redis adiado | Aceita |
| ADR-009 | Dinheiro em BRL armazenado como centavos inteiros | Aceita | | ADR-009 | Dinheiro em BRL armazenado como centavos inteiros | Aceita |
| ADR-010 | Home com estrutura fixa e CMS tipado, sem page builder | Aceita | | ADR-010 | Home com estrutura fixa e CMS tipado, sem page builder | Aceita |
| ADR-011 | Cloudflare R2 (S3-compatible) como storage de objetos em produção | 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-014 | Deploy via Dokploy Compose com imagem imutável por SHA no GHCR | Aceita |
--- ---

View File

@@ -2,7 +2,7 @@ schema: spec-driven
context: | context: |
Fonte de verdade: SPEC.md na raiz. Precedência: instrução do dono do produto > SPEC.md > ADRs > testes > convenções. Fonte de verdade: SPEC.md na raiz. Precedência: instrução do dono do produto > SPEC.md > ADRs > testes > convenções.
Produto: plataforma de assessoria de eventos, single-tenant, MVP. UI em pt-BR, timezone America/Fortaleza, BRL. Produto: plataforma de assessoria de eventos, single-tenant, MVP. UI em pt-BR, timezone America/Sao_Paulo, atuação em São Paulo (capital), BRL.
Stack: Laravel 13, Filament 5 (/admin), Livewire 4 + Blade + Alpine + Tailwind (site público), Stack: Laravel 13, Filament 5 (/admin), Livewire 4 + Blade + Alpine + Tailwind (site público),
PostgreSQL, FrankenPHP regular mode (sem worker mode), Vite, Pest 4 + Pest Browser, database queue. PostgreSQL, FrankenPHP regular mode (sem worker mode), Vite, Pest 4 + Pest Browser, database queue.
Arquitetura: monólito modular. Interface -> Application (Actions/Queries) -> Domain (Enums/VOs) -> Infrastructure. Arquitetura: monólito modular. Interface -> Application (Actions/Queries) -> Domain (Enums/VOs) -> Infrastructure.

View File

@@ -1,7 +1,7 @@
# container-runtime Specification # container-runtime Specification
## Purpose ## Purpose
TBD - created by archiving change setup-foundation. Update Purpose after archive. Define the production container image for the application: a reproducible multi-stage FrankenPHP build serving the public directory, run in regular mode as a non-root user, shared by web/queue/scheduler processes, with no secrets in layers and a healthcheck on `/up`.
## Requirements ## Requirements
### Requirement: Production image uses multi-stage FrankenPHP build ### Requirement: Production image uses multi-stage FrankenPHP build

View File

@@ -1,7 +1,7 @@
# design-tokens Specification # design-tokens Specification
## Purpose ## Purpose
TBD - created by archiving change setup-foundation. Update Purpose after archive. Centralize the public site's design tokens so the interface implements the Heritage Editorial system from DESIGN.md (EB Garamond, 8px rhythm, zero radius, 1120px container, paper/olive/sage/ink palette), honoring reduced motion and WCAG AA contrast without card-shadow hierarchy.
## Requirements ## Requirements
### Requirement: Design tokens are centralized for the public site ### Requirement: Design tokens are centralized for the public site

View File

@@ -1,7 +1,7 @@
# health-check Specification # health-check Specification
## Purpose ## Purpose
TBD - created by archiving change setup-foundation. Update Purpose after archive. Expose a public `GET /up` healthcheck that responds quickly and without authentication, exposes no secrets, and fails when the application cannot boot, so orchestrators and CI can verify availability.
## Requirements ## Requirements
### Requirement: Public health endpoint responds without authentication ### Requirement: Public health endpoint responds without authentication

View File

@@ -1,7 +1,7 @@
# internal-authentication Specification # internal-authentication Specification
## Purpose ## Purpose
TBD - created by archiving change setup-foundation. Update Purpose after archive. Provide session-based authentication for the internal Filament panel at `/admin`, limited to two roles (admin and assistant), with unique emails, password reset without enumeration, inactive users denied, and user management restricted to admins.
## Requirements ## Requirements
### Requirement: Internal users authenticate via Filament panel ### Requirement: Internal users authenticate via Filament panel