| 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).
@@ -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 0–1):** 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 0–1):** 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.
- 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:
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
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
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
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
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.