Files
amare/SPEC.md
manoel freitas 1e215ac3d2
Some checks failed
CI / unit (push) Has been cancelled
CI / feature (push) Has been cancelled
CI / browser (push) Has been cancelled
CI / container (push) Has been cancelled
CI / static (push) Has been cancelled
docs: alinhar remotes e registry para Gitea
Origin e deploy passam a documentar git.hellomanoel.com;
GitHub/GHCR ficam como legado/backup.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 14:35:20 -03:00

69 KiB
Raw Permalink Blame History

SPEC.md — MVP da Plataforma de Assessoria de Eventos

Documento normativo para desenvolvimento orientado por especificação. Este arquivo é a fonte de verdade para agentes como Cursor, Claude Code e outros agentes de implementação.


0. Metadados

Campo Valor
Produto Plataforma de Assessoria de Eventos
Tipo Aplicação web single-tenant
Estágio MVP
Status da especificação Aprovada para implementação
Idioma da interface Português do Brasil (pt-BR)
Timezone padrão America/Sao_Paulo
Cidade de atuação São Paulo (capital)
Moeda BRL, sem conversão entre moedas
Princípio principal YAGNI — implementar somente o necessário para validar o produto
Arquitetura Monólito modular Laravel
Área interna Filament
Á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
Banco de dados PostgreSQL
Testes Pest e Pest Browser/Playwright

0.1 Vocabulário normativo

  • MUST / DEVE: requisito obrigatório.
  • MUST NOT / NÃO DEVE: comportamento proibido.
  • SHOULD / DEVERIA: recomendação forte, dispensável apenas com justificativa registrada.
  • MAY / PODE: opção permitida.

0.2 Ordem de precedência

Em caso de conflito, seguir esta ordem:

  1. Instrução explícita mais recente do responsável pelo produto.
  2. Este SPEC.md.
  3. ADRs aceitos no repositório.
  4. Testes automatizados existentes.
  5. Convenções já consolidadas no código.
  6. Preferência do agente ou da biblioteca.

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

Antes de implementar qualquer mudança, o agente DEVE:

  1. Ler este arquivo integralmente.
  2. Inspecionar a estrutura atual do repositório.
  3. Identificar o requisito funcional pelo ID.
  4. Listar os arquivos que pretende criar ou alterar.
  5. Implementar uma fatia vertical pequena e funcional.
  6. Criar ou atualizar os testes correspondentes.
  7. Executar os gates de qualidade aplicáveis.
  8. Informar o que foi concluído, o que permanece pendente e qualquer desvio da especificação.

1.1 Regras de comportamento do agente

O agente:

  • DEVE priorizar a solução mais simples que satisfaça os critérios de aceite.
  • DEVE reutilizar recursos nativos de Laravel, Filament e Livewire antes de adicionar dependências.
  • DEVE manter Filament Resources e componentes Livewire finos.
  • DEVE colocar regras de negócio em classes testáveis de domínio ou aplicação.
  • DEVE adicionar testes antes de marcar um requisito como concluído.
  • DEVE preservar compatibilidade com PostgreSQL e com o contêiner de produção.
  • DEVE trabalhar em uma fase do backlog por vez, salvo instrução explícita.
  • NÃO DEVE criar funcionalidades listadas em “Fora do MVP”.
  • NÃO DEVE introduzir microserviços, uma SPA separada, API pública, Redis ou mensageria externa.
  • NÃO DEVE criar abstrações genéricas sem ao menos dois usos concretos.
  • NÃO DEVE criar RepositoryInterface, BaseService, BaseAction ou “helpers” genéricos por antecipação.
  • NÃO DEVE colocar regras financeiras diretamente em views, Resources, Models observers ou callbacks de formulário.
  • NÃO DEVE usar float para dinheiro.
  • NÃO DEVE persistir status derivados que possam ser calculados corretamente a partir dos dados fonte.

1.2 Entrega incremental

Cada fatia vertical deve, quando aplicável, incluir:

  • migration;
  • enum ou regra de domínio;
  • model e relacionamentos;
  • Action/Query;
  • Policy;
  • interface Filament ou Livewire;
  • factories e seed mínimo;
  • testes unitários e/ou feature;
  • teste browser quando a jornada for crítica;
  • documentação curta de qualquer decisão não óbvia.

2. Visão do produto

O MVP é uma aplicação única para uma assessora de eventos ou uma equipe pequena. O produto possui duas superfícies integradas:

  1. Site público premium, usado para apresentar a marca, construir confiança e converter visitantes em leads.
  2. Área interna operacional, usada para gerenciar leads, eventos, tarefas, fornecedores, orçamento, pagamentos manuais, documentos e conteúdo do site.

2.1 Hipótese de produto

Uma assessora adotará o sistema quando ele:

  • ajudar a vender melhor;
  • reduzir planilhas e informações dispersas;
  • mostrar claramente o que precisa de atenção;
  • organizar o evento sem exigir uma mudança radical no fluxo de trabalho;
  • transmitir profissionalismo aos possíveis clientes.

2.2 Resultados que o MVP precisa provar

  • O site converte visitantes em leads qualificados.
  • A assessora acompanha o pipeline sem planilhas externas.
  • Um lead conquistado é convertido em evento sem redigitação.
  • A assessora gerencia tarefas, fornecedores, orçamento e pagamentos manuais.
  • O dashboard destaca pendências reais do dia.
  • O site é visualmente forte, rápido, acessível e responsivo.
  • A aplicação pode ser implantada e atualizada com segurança por pipeline automatizado.

2.3 Métricas iniciais

Dimensão Métrica Meta inicial
Aquisição Conclusão do formulário de briefing Medir baseline e melhorar por iteração
Comercial Leads ativos sem próxima ação 0 ao fim de cada dia útil
Operação Tarefas vencidas sem responsável 0
Financeiro Itens de orçamento sem valor ou status Menos de 5% por evento ativo
Qualidade Jornadas E2E críticas passando 100% antes de deploy
Confiabilidade Erros não tratados Alerta imediato e tendência decrescente

3. Personas e acesso

3.1 Visitante

Objetivo: entender os serviços, confiar na assessora, ver eventos reais e solicitar contato.

Permissões:

  • acessar apenas as rotas públicas;
  • enviar o formulário de briefing;
  • não possui conta nem área autenticada.

3.2 Assessora administradora

Objetivo: gerenciar toda a operação e o conteúdo do site.

Permissões:

  • acesso integral ao Filament;
  • gerenciar usuários internos;
  • gerenciar configurações e conteúdos públicos;
  • criar, atualizar e excluir entidades operacionais conforme Policies;
  • visualizar auditoria.

3.3 Assistente

Objetivo: atualizar a rotina operacional dos eventos.

Permissões:

  • acessar leads, eventos, tarefas, fornecedores, orçamento, pagamentos e documentos;
  • não gerenciar usuários;
  • não alterar configurações globais do site;
  • não acessar ou apagar auditoria;
  • não executar exclusões críticas sem autorização.

3.4 Papéis

Usar enum simples:

enum UserRole: string
{
    case Admin = 'admin';
    case Assistant = 'assistant';
}

Não instalar sistema de permissões granular no MVP.


4. Escopo

Recorte vigente do lançamento (ADR-016). O escopo aprovado para o lançamento de 31/08/2026 é o site institucional: Fases 0 e 1. As Fases 2 a 5 — CRM de leads, conversão de lead em evento, eventos, tarefas, fornecedores, orçamento, pagamentos manuais, documentos, dashboard orientado a exceções e auditoria — permanecem especificadas neste documento mas ficam adiadas, sem data.

A §4.1 abaixo descreve o produto completo, não o recorte do lançamento. Os itens marcados como adiados estão fora do que se constrói agora. Ver §18 para a divisão por fase e §23 para as condições de conclusão de cada recorte.

4.1 Incluído no MVP

No recorte do lançamento (Fases 01):

  • site público;
  • CMS interno do site;
  • formulário de briefing;
  • usuários internos e papéis simples;
  • SEO básico;
  • acessibilidade automatizada;
  • CI/CD e deploy em contêiner com FrankenPHP.

Adiados para depois do lançamento (Fases 25, ver ADR-016):

  • CRM de leads;
  • conversão de lead em evento;
  • cadastro e visão consolidada de eventos;
  • checklist e tarefas;
  • diretório e vínculo de fornecedores;
  • orçamento por evento;
  • pagamentos inseridos manualmente;
  • documentos vinculados a leads e eventos;
  • dashboard orientado a exceções;
  • notificações internas e por e-mail para novos leads;
  • auditoria de ações críticas.

Adiado não é o mesmo que fora do MVP: os itens acima seguem especificados neste documento e continuam sendo o produto pretendido. A §4.2 lista o que NÃO DEVE ser implementado em nenhum momento.

4.2 Fora do MVP

Os itens abaixo NÃO DEVEM ser implementados:

  • portal ou login para cliente final;
  • convites digitais;
  • RSVP;
  • gestão de convidados;
  • check-in ou QR Code;
  • mapa de mesas;
  • pagamento online;
  • Pix, boleto, cartão ou gateway de pagamento;
  • conciliação bancária;
  • emissão fiscal;
  • assinatura eletrônica;
  • geração jurídica de contratos;
  • cobrança automática;
  • integração oficial com WhatsApp;
  • chat interno;
  • comunicação omnichannel;
  • multi-tenancy;
  • SaaS para múltiplas assessorias;
  • aplicativo nativo;
  • PWA offline avançada;
  • push notifications;
  • marketplace de fornecedores;
  • avaliações públicas de fornecedores;
  • IA generativa;
  • transcrição ou resumo automático de reuniões;
  • leitura automática de contratos;
  • microserviços;
  • event sourcing;
  • CQRS arquitetural;
  • Kafka, RabbitMQ, SQS ou Redis obrigatório;
  • mecanismo externo de busca;
  • API pública;
  • editor visual de páginas semelhante a page builder;
  • Kanban com drag-and-drop para leads;
  • editor de templates de checklist.

4.3 Regra de mudança de escopo

Uma funcionalidade fora do MVP só poderá entrar quando:

  1. desbloquear uma jornada já definida; ou
  2. resolver um problema observado em uso real; e
  3. tiver critério de aceite e impacto técnico documentados.

“Pode ser útil no futuro” não é justificativa suficiente.


5. Arquitetura de informação

5.1 Rotas públicas

Método Rota Nome sugerido Finalidade
GET / home Home editorial
GET /servicos services.index Lista de serviços publicados
GET /portfolio portfolio.index Lista de casos publicados
GET /portfolio/{slug} portfolio.show Detalhe de caso
GET /sobre about História, método e credenciais
GET /contato contact Briefing de contato
GET /privacidade privacy Política de privacidade
GET /sitemap.xml sitemap Sitemap público
GET /robots.txt robots Política de crawling
GET /up health Healthcheck sem autenticação

5.2 Painel interno

Prefixo: /admin.

Navegação:

Dashboard
Comercial
├── Leads
└── Atividades
Eventos
├── Eventos
├── Tarefas
├── Fornecedores
├── Orçamento e pagamentos
└── Documentos
Conteúdo do site
├── Serviços
├── Portfólio
├── Depoimentos
└── Configurações
Administração
├── Usuários
└── Auditoria

5.3 Páginas customizadas obrigatórias

  • Dashboard: Filament Page customizada com widgets orientados a exceção.
  • Detalhe do evento: página customizada do Resource com resumo operacional.
  • Briefing público: Blade + Controller (POST /contato), ver §11.2.
  • Home: Blade com componentes de design reutilizáveis.

5.4 Decisões de UX YAGNI

  • Pipeline de leads será tabela com filtros e ações rápidas.
  • Não criar Kanban no MVP.
  • Conteúdo da home terá estrutura fixa; textos e itens serão editáveis.
  • Não criar page builder genérico.
  • Ações destrutivas precisam de confirmação.
  • O dashboard deve priorizar pendências, não gráficos decorativos.

6. Design e experiência do site público

O site público é requisito funcional, não apenas acabamento visual.

6.1 Princípios visuais

  • aparência editorial e premium;
  • fotografia grande e bem tratada;
  • tipografia com hierarquia clara;
  • espaçamento generoso;
  • poucos elementos simultâneos;
  • transições sutis;
  • contraste acessível;
  • mobile-first;
  • CTAs claros;
  • sem aparência de template administrativo.

6.2 Estrutura da home

A home DEVE conter, nesta ordem aproximada:

  1. header e navegação;
  2. hero com proposta de valor e CTA;
  3. manifesto da marca;
  4. resumo dos serviços em destaque;
  5. casos selecionados do portfólio;
  6. método de trabalho (4 passos);
  7. depoimentos;
  8. posicionamento/perfil;
  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.

6.3 Design tokens mínimos

Centralizar tokens de:

  • famílias tipográficas;
  • escala de fonte;
  • espaçamentos;
  • raio de borda;
  • largura de container;
  • cores de fundo, texto, borda, destaque e estados;
  • sombras;
  • duração e easing de transições.

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

  • Imagens públicas DEVERÃO possuir texto alternativo.
  • A aplicação DEVERÁ validar extensão, MIME e tamanho.
  • A aplicação DEVERÁ gerar ou servir variantes responsivas.
  • Imagens fora da primeira dobra DEVERÃO usar lazy loading.
  • Dimensões DEVERÃO ser reservadas para evitar layout shift.
  • Não armazenar blobs de imagem no PostgreSQL.
  • 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

  • navegação completa por teclado;
  • foco visível;
  • labels associados aos campos;
  • mensagens de erro ligadas ao campo correspondente;
  • landmarks semânticos;
  • um único h1 por página;
  • ordem coerente de headings;
  • contraste compatível com WCAG AA;
  • suporte a prefers-reduced-motion;
  • nenhuma issue automatizada crítica ou séria nas jornadas cobertas.

6.6 Performance e SEO

Metas:

Métrica Meta
LCP ≤ 2,5 s nas páginas principais
CLS ≤ 0,1
INP ≤ 200 ms
Erros JS no console 0 nas jornadas críticas

SEO obrigatório:

  • title e meta description por página;
  • canonical;
  • Open Graph;
  • sitemap;
  • robots;
  • slug legível;
  • conteúdo publicado somente quando published_at estiver preenchido;
  • dados estruturados básicos quando aplicáveis;
  • páginas de portfólio indexáveis.

7. Requisitos funcionais

7.1 Site público e CMS

WEB-01 — Home editorial

Prioridade: P0

A home deve apresentar proposta, serviços, casos, método, depoimentos e CTA.

Aceite:

Given que existem serviços, casos e depoimentos publicados
When um visitante acessa a home
Then o conteúdo publicado é exibido na ordem configurada
And a página funciona em viewport desktop e mobile
And não existem erros JavaScript no console
And o CTA leva ao briefing

WEB-02 — Serviços

Prioridade: P0

Campos mínimos:

  • título;
  • slug;
  • resumo;
  • descrição;
  • imagem de capa opcional;
  • texto alternativo;
  • ordem;
  • destaque;
  • published_at.

Regras:

  • slug deve ser único;
  • serviço não publicado não aparece no site;
  • exclusão deve exigir confirmação;
  • admin pode gerenciar; assistant não pode.

WEB-03 — Portfólio

Prioridade: P0

Campos mínimos:

  • título;
  • slug;
  • resumo;
  • tipo de evento;
  • cidade/local opcional;
  • data do evento opcional;
  • desafio;
  • solução;
  • resultado opcional;
  • imagem de capa;
  • galeria ordenada;
  • destaque;
  • published_at;
  • metadados SEO opcionais.

Aceite:

Given um caso salvo como rascunho
When a assessora preenche os campos obrigatórios e publica o caso
Then a rota pública pelo slug passa a responder 200
And o caso aparece na listagem pública
And as imagens possuem dimensões reservadas e textos alternativos

WEB-04 — Depoimentos

Prioridade: P0

Campos:

  • texto;
  • nome da pessoa;
  • contexto ou tipo de evento opcional;
  • fotografia opcional;
  • ordem;
  • destaque;
  • published_at.

WEB-05 — Briefing de contato

Prioridade: P0

Campos públicos:

  • nome completo;
  • e-mail;
  • telefone/WhatsApp;
  • tipo de evento;
  • data ou período desejado opcional;
  • cidade;
  • número estimado de convidados opcional;
  • serviço de interesse opcional;
  • mensagem/principal preocupação;
  • origem de marketing capturada quando disponível;
  • aceite do aviso de privacidade.

Regras:

  • validar no servidor;
  • usar honeypot e rate limiting;
  • impedir duplo envio acidental;
  • enviar e-mail de confirmação quando o serviço de e-mail estiver configurado;
  • 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:

Given um visitante no formulário de briefing
When ele envia dados válidos uma única vez
Then um lead é criado com status Novo
And a tela mostra confirmação
And a assessora recebe notificação interna
And uma nova submissão causada por duplo clique não cria lead duplicado

WEB-06 — Configurações do site

Prioridade: P0

Singleton gerenciável apenas por admin:

  • nome da marca;
  • texto e CTA do hero;
  • resumo institucional;
  • e-mail;
  • telefone;
  • endereço/cidade opcional;
  • links sociais;
  • title padrão;
  • description padrão;
  • imagem Open Graph padrão;
  • scripts de analytics opcionais, desabilitados por padrão.

Não criar sistema genérico de chave/valor se um singleton tipado resolver.

WEB-07 — Páginas institucionais

Prioridade: P1

  • Sobre;
  • Política de privacidade;
  • página 404 com identidade visual;
  • página 500 segura e sem stack trace em produção.

7.2 Leads e CRM

CRM-01 — Cadastro de lead

Prioridade: P0

Lead pode ser criado:

  • automaticamente pelo briefing;
  • manualmente no Filament.

Campos:

  • nome;
  • e-mail;
  • telefone;
  • tipo de evento;
  • data estimada;
  • cidade;
  • convidados estimados;
  • mensagem;
  • origem;
  • status;
  • próxima ação em;
  • tipo da próxima ação;
  • observação da próxima ação;
  • motivo da perda;
  • converted_event_id ou relacionamento equivalente;
  • timestamps.

CRM-02 — Pipeline

Prioridade: P0

Estados permitidos:

enum LeadStatus: string
{
    case New = 'new';
    case Contacted = 'contacted';
    case Meeting = 'meeting';
    case Proposal = 'proposal';
    case Negotiation = 'negotiation';
    case Won = 'won';
    case Lost = 'lost';
}

Transições permitidas no MVP:

  • qualquer estado ativo pode avançar ou retroceder para outro estado ativo;
  • won somente por conversão bem-sucedida ou ação administrativa explícita;
  • lost exige motivo;
  • lead convertido não pode voltar para estado ativo sem operação manual administrativa documentada;
  • lead perdido pode ser reaberto por admin, limpando motivo de perda e criando auditoria.

CRM-03 — Próxima ação

Prioridade: P0

  • lead ativo pode possuir data, tipo e observação;
  • lead ativo sem próxima ação deve aparecer no dashboard;
  • próxima ação passada deve aparecer como atrasada;
  • lead won ou lost não precisa de próxima ação.

CRM-04 — Histórico

Prioridade: P0

Registrar atividades:

  • nota manual;
  • alteração de status;
  • alteração de próxima ação;
  • criação pelo site;
  • conversão em evento;
  • marcação como perdido ou reaberto.

O histórico deve ser cronológico e imutável pela interface comum. Admin pode remover somente em operação excepcional auditada.

CRM-05 — Busca e filtros

Prioridade: P0

Filtrar ou buscar por:

  • nome;
  • e-mail;
  • telefone;
  • status;
  • origem;
  • tipo de evento;
  • data estimada;
  • próxima ação;
  • leads sem próxima ação.

CRM-06 — Conversão em evento

Prioridade: P0

A conversão:

  • DEVE ser idempotente;
  • DEVE executar em transação;
  • DEVE criar somente um evento;
  • DEVE copiar dados relevantes do lead;
  • DEVE vincular lead e evento;
  • DEVE criar checklist padrão;
  • DEVE alterar lead para won;
  • DEVE criar atividade e auditoria;
  • DEVE rejeitar uma segunda conversão.

Aceite:

Given um lead ainda não convertido
When a assessora executa Converter em evento
Then um único evento é criado
And o checklist padrão é criado
And o lead é marcado como Conquistado
And uma segunda execução não cria outro evento

CRM-07 — Perda do lead

Prioridade: P0

  • motivo é obrigatório;
  • próxima ação deve ser removida;
  • mudança deve aparecer no histórico;
  • motivo não é visível em área pública.

7.3 Eventos

EVT-01 — Cadastro de evento

Prioridade: P0

Campos:

  • título;
  • tipo;
  • lead de origem opcional;
  • nome do cliente;
  • e-mail do cliente;
  • telefone do cliente;
  • data e hora de início opcionais durante planejamento;
  • data e hora de fim opcionais;
  • local;
  • cidade;
  • status;
  • orçamento-alvo em centavos opcional;
  • resumo;
  • observações internas;
  • responsável interno opcional.

EVT-02 — Estados do evento

enum EventStatus: string
{
    case Planning = 'planning';
    case Confirmed = 'confirmed';
    case InProgress = 'in_progress';
    case Completed = 'completed';
    case Cancelled = 'cancelled';
}

Regras:

  • novo evento começa em planning;
  • confirmed exige data de início;
  • in_progress exige data de início;
  • completed registra completed_at;
  • cancelled registra motivo opcional e auditoria;
  • evento cancelado não aparece entre próximos eventos ativos;
  • reabertura de evento concluído ou cancelado exige admin e auditoria.

EVT-03 — Visão consolidada

Prioridade: P0

A página do evento deve mostrar:

  • resumo e status;
  • cliente e contatos;
  • dias restantes;
  • próximas tarefas;
  • tarefas vencidas;
  • fornecedores vinculados;
  • totais financeiros;
  • próximos pagamentos;
  • documentos recentes;
  • atalhos para criar tarefa, vínculo de fornecedor, item de orçamento, pagamento e documento.

EVT-04 — Listagem e filtros

Prioridade: P0

Filtros:

  • status;
  • tipo;
  • período;
  • responsável;
  • eventos nos próximos 7, 30 e 90 dias;
  • eventos sem data;
  • busca por título, cliente, cidade ou local.

7.4 Tarefas

TSK-01 — Checklist do evento

Prioridade: P0

Campos:

  • evento;
  • título;
  • descrição opcional;
  • responsável opcional;
  • prazo opcional;
  • prioridade;
  • status;
  • posição/ordem;
  • completed_at;
  • completed_by.

Enums:

enum TaskPriority: string
{
    case Low = 'low';
    case Medium = 'medium';
    case High = 'high';
    case Critical = 'critical';
}

enum TaskStatus: string
{
    case Pending = 'pending';
    case InProgress = 'in_progress';
    case Completed = 'completed';
}

TSK-02 — Regras de conclusão

  • concluir tarefa preenche completed_at e completed_by;
  • reabrir tarefa limpa ambos;
  • tarefa concluída não é considerada vencida;
  • tarefa pendente com prazo anterior a hoje é vencida;
  • tarefa sem responsável é explicitamente sinalizada;
  • exclusão exige confirmação.

TSK-03 — Checklist padrão

Prioridade: P0

O MVP deve possuir um checklist padrão definido em seed ou configuração de código versionada.

  • checklist deve ser criado na conversão de lead;
  • tarefas podem possuir prazo relativo à data do evento quando esta existir;
  • se a data do evento ainda não existir, tarefas relativas permanecem sem prazo;
  • ao definir posteriormente a data do evento, a aplicação pode calcular prazos ausentes uma única vez;
  • editor de templates fica fora do MVP.

Checklist inicial sugerido:

  1. confirmar briefing e escopo;
  2. definir data e local;
  3. definir orçamento-alvo;
  4. mapear fornecedores essenciais;
  5. confirmar fornecedores selecionados;
  6. revisar cronograma geral;
  7. realizar reunião final;
  8. confirmar contatos operacionais;
  9. revisar pagamentos pendentes;
  10. concluir evento e registrar aprendizados.

TSK-04 — Visão global de tarefas

Prioridade: P1

Listar tarefas de todos os eventos com filtros por:

  • responsável;
  • status;
  • prioridade;
  • evento;
  • vencidas;
  • hoje;
  • próximos 7 dias;
  • sem responsável.

7.5 Fornecedores

VEN-01 — Diretório

Prioridade: P0

Campos:

  • nome;
  • categoria;
  • nome do contato opcional;
  • e-mail opcional;
  • telefone opcional;
  • cidade/região;
  • site ou rede social opcional;
  • observações internas;
  • ativo/inativo.

Categorias devem usar enum ou tabela fixa simples. Não criar CRUD de categorias no MVP.

Categorias iniciais:

  • espaço;
  • buffet;
  • bebidas;
  • decoração;
  • fotografia;
  • filmagem;
  • música/DJ;
  • som e iluminação;
  • mobiliário;
  • celebrante/cerimonial;
  • segurança;
  • limpeza;
  • transporte;
  • hospedagem;
  • gráfica/comunicação;
  • outros.

VEN-02 — Vínculo ao evento

Prioridade: P0

Campos:

  • evento;
  • fornecedor;
  • status;
  • contato específico opcional;
  • observações;
  • valor de referência opcional em centavos.

Status:

enum EventVendorStatus: string
{
    case Quoted = 'quoted';
    case Selected = 'selected';
    case Contracted = 'contracted';
    case Discarded = 'discarded';
}

Um fornecedor não deve ser vinculado duas vezes ao mesmo evento na mesma categoria sem justificativa explícita. Usar constraint adequada conforme o modelo final.


7.6 Orçamento e pagamentos manuais

FIN-01 — Item de orçamento

Prioridade: P0

Campos:

  • evento;
  • categoria;
  • descrição;
  • fornecedor opcional;
  • valor planejado em centavos opcional;
  • valor acordado em centavos opcional;
  • status;
  • observações;
  • posição/ordem.

Status:

enum BudgetItemStatus: string
{
    case Planned = 'planned';
    case Quoted = 'quoted';
    case Approved = 'approved';
    case Contracted = 'contracted';
    case Cancelled = 'cancelled';
}

FIN-02 — Dinheiro

Regras obrigatórias:

  • todos os valores monetários são BRL;
  • armazenar valores em centavos com BIGINT;
  • nunca usar float em domínio, Action ou teste;
  • formatar na UI como moeda brasileira;
  • entradas de formulário devem ser convertidas de string decimal para centavos;
  • valores não podem ser negativos;
  • não implementar conversão de moeda.

Criar Value Object pequeno somente se ele reduzir duplicação e bugs reais:

final readonly class Money
{
    public function __construct(public int $cents) {}
}

FIN-03 — Pagamento manual

Prioridade: P0

Campos:

  • evento;
  • item de orçamento opcional;
  • descrição;
  • valor em centavos;
  • vencimento;
  • data de pagamento opcional;
  • método opcional;
  • comprovante opcional;
  • observações;
  • criado por;
  • atualizado por.

Métodos permitidos:

  • Pix;
  • transferência;
  • dinheiro;
  • cartão;
  • boleto;
  • outro.

O método é apenas informativo. Nenhum pagamento é processado pelo sistema.

FIN-04 — Status derivado do pagamento

Não persistir status quando puder ser derivado:

paid_at != null                       => paid
paid_at == null e due_date < hoje     => overdue
paid_at == null e due_date >= hoje    => pending

“Vencendo em breve” é uma apresentação calculada para vencimentos entre hoje e hoje + 7 dias.

FIN-05 — Totais do evento

Calcular:

  • planejado: soma de planned_amount_cents não cancelados;
  • acordado: soma de agreed_amount_cents não cancelados;
  • pago: soma de pagamentos com paid_at;
  • pendente: soma de pagamentos sem paid_at;
  • vencido: soma de pagamentos sem paid_at e com vencimento passado;
  • saldo do acordado: max(acordado - pago, 0).

Não criar tabela de totais materializados no MVP. Usar Query dedicada e índices adequados.

FIN-06 — Consistência financeira

  • pagamento não pode ter valor zero ou negativo;
  • data de pagamento pode ser anterior, igual ou posterior ao vencimento;
  • comprovante é opcional;
  • alteração e exclusão de pagamento geram auditoria;
  • exclusão deve ser restrita a admin ou possuir confirmação reforçada;
  • a soma de pagamentos pode superar o valor acordado; a UI deve sinalizar, não bloquear, pois ajustes reais podem existir;
  • nenhum módulo contábil ou fiscal será criado.

Aceite:

Given um evento com item acordado de R$ 3.000,00
And dois pagamentos manuais de R$ 1.000,00 e R$ 2.000,00
When ambos possuem data de pagamento
Then o total pago é R$ 3.000,00
And o saldo acordado é R$ 0,00
And nenhum pagamento aparece como pendente ou vencido

7.7 Documentos

DOC-01 — Upload vinculado

Prioridade: P1

Documentos podem pertencer a:

  • lead; ou
  • evento.

Campos:

  • nome exibido;
  • path privado;
  • MIME;
  • tamanho;
  • categoria;
  • observação;
  • usuário que enviou;
  • timestamps.

Regras:

  • arquivo deve ser privado por padrão;
  • download requer autenticação e Policy;
  • validar allowlist de tipos;
  • limite inicial configurável, padrão 10 MB;
  • nome original não deve determinar o path físico;
  • não armazenar arquivos no banco;
  • exclusão gera auditoria.

Categorias iniciais:

  • briefing;
  • proposta;
  • contrato;
  • orçamento;
  • comprovante;
  • referência visual;
  • cronograma;
  • outro.

7.8 Dashboard e notificações

DASH-01 — Dashboard orientado a atenção

Prioridade: P0

O dashboard deve responder: “O que precisa da minha atenção hoje?”

Widgets obrigatórios:

  • leads novos;
  • leads ativos sem próxima ação;
  • próximas ações vencidas;
  • eventos nos próximos 7, 30 e 90 dias;
  • tarefas vencidas;
  • tarefas de hoje;
  • tarefas sem responsável;
  • pagamentos vencidos;
  • pagamentos vencendo em até 7 dias;
  • atalhos para novo lead, evento, fornecedor e caso de portfólio.

Cada item deve ser acionável e levar ao registro correspondente.

DASH-02 — Notificação de novo lead

Prioridade: P0

  • criar database notification para admins;
  • enviar e-mail assíncrono quando configurado;
  • usar database queue;
  • falha de notificação não pode reverter a criação do lead;
  • job deve ser idempotente quando possível.

DASH-03 — Lembrete diário

Prioridade: P1

Scheduler diário pode criar notificação resumida com:

  • próximas ações vencidas;
  • tarefas vencidas;
  • pagamentos vencidos.

Não enviar resumo se não houver pendências.


7.9 Administração e auditoria

ADM-01 — Usuários internos

Prioridade: P0

  • admin cria e desativa usuários;
  • e-mail único;
  • papel admin ou assistant;
  • usuário inativo não autentica;
  • reset de senha seguro;
  • acesso ao Filament restrito explicitamente.

ADM-02 — Auditoria

Prioridade: P0

Ações auditáveis:

  • conversão de lead;
  • marcação de lead perdido ou reaberto;
  • mudança financeira;
  • exclusão de pagamento;
  • exclusão de documento;
  • publicação ou despublicação de conteúdo;
  • exclusão de entidade principal;
  • mudança de papel ou ativação de usuário;
  • reabertura de evento concluído/cancelado.

Campos mínimos:

  • usuário opcional;
  • ação;
  • tipo da entidade;
  • ID da entidade;
  • metadados JSON sem dados sensíveis desnecessários;
  • IP opcional;
  • request ID;
  • timestamp.

Auditoria não precisa ser um event sourcing. Registrar apenas operações críticas.


8. Modelo de domínio e banco de dados

8.1 Módulos

Módulo Responsabilidade
Marketing Conteúdo público e conversão
CRM Leads, atividades e conversão
Events Eventos, tarefas e documentos
Vendors Fornecedores e vínculos
Finance Orçamento e pagamentos manuais
Identity Usuários, acesso e auditoria

8.2 Tabelas obrigatórias

users

  • id bigint PK;
  • name varchar;
  • email varchar unique;
  • email_verified_at timestamp nullable;
  • password varchar;
  • role varchar indexed;
  • is_active boolean default true indexed;
  • remember token;
  • timestamps.

site_settings

Singleton:

  • id bigint PK;
  • brand_name;
  • logo_path nullable;
  • logo_alt nullable;
  • hero_eyebrow nullable;
  • hero_title;
  • hero_subtitle;
  • 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;
  • email;
  • phone;
  • city nullable;
  • social_links jsonb;
  • default_meta_title;
  • default_meta_description;
  • default_og_image_path nullable;
  • default_og_image_alt nullable;
  • analytics_enabled boolean default false;
  • timestamps.

services

  • id;
  • title;
  • slug unique;
  • summary;
  • description text;
  • cover_image_path nullable;
  • cover_image_alt nullable;
  • sort_order integer indexed;
  • is_featured boolean indexed;
  • published_at timestamp nullable indexed;
  • timestamps;
  • soft delete opcional somente se recuperação for necessária.

portfolio_cases

  • id;
  • title;
  • slug unique;
  • summary;
  • event_type;
  • city nullable;
  • venue nullable;
  • event_date date nullable;
  • challenge text;
  • solution text;
  • result text nullable;
  • cover_image_path;
  • cover_image_alt;
  • is_featured boolean indexed;
  • sort_order integer indexed;
  • published_at timestamp nullable indexed;
  • meta_title nullable;
  • meta_description nullable;
  • timestamps.

portfolio_images

  • id;
  • portfolio_case_id FK cascade;
  • path;
  • alt_text;
  • caption nullable;
  • sort_order integer;
  • timestamps;
  • index composto por portfolio_case_id, sort_order.

testimonials

  • id;
  • quote text;
  • author_name;
  • context nullable;
  • photo_path nullable;
  • photo_alt nullable;
  • sort_order integer;
  • is_featured boolean indexed;
  • published_at timestamp nullable indexed;
  • timestamps.

leads

  • id;
  • name;
  • email nullable indexed;
  • phone nullable indexed;
  • event_type;
  • estimated_event_date date nullable indexed;
  • city nullable;
  • estimated_guests integer nullable;
  • message text nullable;
  • source varchar indexed;
  • status varchar indexed;
  • next_action_at timestamp nullable indexed;
  • next_action_type nullable;
  • next_action_notes text nullable;
  • lost_reason text nullable;
  • converted_event_id nullable unique;
  • privacy_notice_accepted_at timestamp nullable;
  • marketing_metadata jsonb nullable;
  • timestamps;
  • soft deletes recomendados para recuperação operacional.

lead_activities

  • id;
  • lead_id FK cascade;
  • user_id FK nullable set null;
  • type varchar indexed;
  • description text;
  • metadata jsonb nullable;
  • created_at;
  • sem updated_at quando possível, pois atividade é append-only.

events

  • id;
  • lead_id FK nullable unique;
  • title;
  • event_type;
  • client_name;
  • client_email nullable;
  • client_phone nullable;
  • starts_at timestamp nullable indexed;
  • ends_at timestamp nullable;
  • venue nullable;
  • city nullable;
  • status varchar indexed;
  • target_budget_cents bigint nullable;
  • summary text nullable;
  • internal_notes text nullable;
  • owner_user_id FK nullable indexed;
  • completed_at timestamp nullable;
  • timestamps;
  • soft deletes recomendados.

event_tasks

  • id;
  • event_id FK cascade indexed;
  • title;
  • description text nullable;
  • assigned_user_id FK nullable indexed;
  • due_at timestamp nullable indexed;
  • priority varchar indexed;
  • status varchar indexed;
  • sort_order integer;
  • relative_due_days integer nullable;
  • completed_at timestamp nullable;
  • completed_by_user_id FK nullable;
  • timestamps;
  • index composto por event_id, status, due_at.

vendors

  • id;
  • name indexed;
  • category varchar indexed;
  • contact_name nullable;
  • email nullable;
  • phone nullable;
  • city_region nullable indexed;
  • website_url nullable;
  • notes text nullable;
  • is_active boolean default true indexed;
  • timestamps;
  • soft deletes opcionais.

event_vendors

  • id;
  • event_id FK cascade indexed;
  • vendor_id FK restrict indexed;
  • category varchar indexed;
  • status varchar indexed;
  • contact_override nullable;
  • reference_amount_cents bigint nullable;
  • notes text nullable;
  • timestamps;
  • índice composto por event_id, category, status.

budget_items

  • id;
  • event_id FK cascade indexed;
  • vendor_id FK nullable set null;
  • category varchar indexed;
  • description;
  • planned_amount_cents bigint nullable;
  • agreed_amount_cents bigint nullable;
  • status varchar indexed;
  • notes text nullable;
  • sort_order integer;
  • timestamps;
  • checks de valores não negativos quando suportado.

payments

  • id;
  • event_id FK cascade indexed;
  • budget_item_id FK nullable set null indexed;
  • description;
  • amount_cents bigint;
  • due_date date indexed;
  • paid_at timestamp nullable indexed;
  • method varchar nullable;
  • proof_path nullable;
  • notes text nullable;
  • created_by_user_id FK;
  • updated_by_user_id FK;
  • timestamps;
  • check amount_cents > 0.

documents

  • id;
  • lead_id FK nullable cascade;
  • event_id FK nullable cascade;
  • display_name;
  • path;
  • mime_type;
  • size_bytes bigint;
  • category varchar indexed;
  • notes text nullable;
  • uploaded_by_user_id FK;
  • timestamps;
  • constraint: exatamente um entre lead_id e event_id deve ser preenchido.

audit_logs

  • id;
  • user_id FK nullable set null indexed;
  • action varchar indexed;
  • auditable_type varchar indexed;
  • auditable_id bigint indexed;
  • metadata jsonb nullable;
  • ip_address nullable;
  • request_id nullable indexed;
  • created_at.

Infraestrutura Laravel

Usar tabelas padrão conforme recursos habilitados:

  • notifications;
  • jobs;
  • job_batches, somente se necessário;
  • failed_jobs;
  • password reset tokens;
  • sessions, caso sessão em banco seja escolhida.

8.3 Integridade e transações

Usar transação em:

  • conversão de lead em evento;
  • criação de evento com checklist;
  • alterações financeiras que gerem múltiplas gravações;
  • exclusões críticas com auditoria;
  • operações que atualizam estado e histórico juntos.

Constraints de banco devem proteger:

  • e-mail único de usuário;
  • slug único;
  • lead convertido uma única vez;
  • evento originado de um único lead;
  • valores financeiros válidos;
  • relacionamentos obrigatórios;
  • documento pertencendo a um único owner lógico.

9. Arquitetura técnica

9.1 Stack

Camada Tecnologia
Runtime PHP com versão minor fixada no Docker
Framework Laravel 13
Admin Filament 5
UI pública Blade + Tailwind + JS vanilla progressivo (sem framework reativo; Livewire 4 confinado ao Filament — ver ADR-015 e §22)
Banco PostgreSQL
Servidor FrankenPHP + Caddy
Assets Vite
Testes Pest 4 + Pest Browser/Playwright
Arquivos Laravel Filesystem + Cloudflare R2 (S3-compatible) em produção
Fila Database queue
Scheduler Laravel Scheduler em processo separado

Caso o projeto seja criado com versões posteriores, o agente deve manter compatibilidade entre as versões instaladas e registrar a decisão. Não fazer upgrade de major version no meio da implementação sem ADR.

9.2 Estilo arquitetural

Monólito modular com dependências orientadas:

Interface (Filament / Livewire / HTTP)
        ↓
Application (Actions / Queries / Data)
        ↓
Domain (Enums / Value Objects / Rules)
        ↓
Infrastructure (Eloquent / Mail / Filesystem / Queue)

9.3 Regras arquiteturais

  • Domain NÃO DEVE depender de Filament ou Livewire.
  • Filament e Livewire chamam Actions e Queries.
  • Eloquent Models podem existir em app/Models e ser usados por Actions/Queries.
  • Não criar repositórios genéricos.
  • Queries de leitura podem usar Eloquent diretamente.
  • Actions devem representar casos de uso, não CRUD trivial.
  • Enums representam estados estáveis.
  • Value Objects somente para conceitos com regra real, como dinheiro.
  • Eventos Laravel somente para efeitos colaterais claros.
  • Policies controlam autorização.
  • Observers devem ser evitados para regras críticas por esconderem fluxo.
  • Soft delete deve ser aplicado seletivamente.
  • Todo arquivo PHP próprio deve usar declare(strict_types=1); quando compatível.

9.4 Estrutura sugerida

app/
├── Application/
│   ├── Actions/
│   │   ├── CRM/
│   │   ├── Events/
│   │   ├── Finance/
│   │   ├── Marketing/
│   │   └── Vendors/
│   ├── Data/
│   └── Queries/
├── Domain/
│   ├── CRM/
│   ├── Events/
│   ├── Finance/
│   ├── Marketing/
│   ├── Vendors/
│   └── Identity/
├── Filament/
│   ├── Pages/
│   ├── Resources/
│   └── Widgets/
├── Livewire/
│   └── PublicSite/
├── Models/
├── Notifications/
├── Policies/
└── Support/

resources/views/
├── components/
├── layouts/
├── livewire/public-site/
└── pages/

tests/
├── Architecture/
├── Browser/
├── Feature/
└── Unit/

Não criar diretórios vazios antecipadamente. Criar quando o primeiro uso existir.

9.5 Actions mínimas esperadas

  • CaptureWebsiteLead;
  • CreateManualLead somente se CRUD padrão não for suficiente;
  • UpdateLeadStatus;
  • ScheduleLeadNextAction;
  • MarkLeadAsLost;
  • ReopenLead;
  • ConvertLeadToEvent;
  • CreateDefaultEventChecklist;
  • CompleteEventTask;
  • ReopenEventTask;
  • RecordManualPayment;
  • UpdateManualPayment;
  • DeleteManualPayment;
  • PublishPortfolioCase;
  • UnpublishPortfolioCase;
  • StorePrivateDocument;
  • WriteAuditLog ou serviço equivalente, sem transformar auditoria em event sourcing.

Não criar Action para todo create/update se o Filament Resource puder salvar de forma segura sem regra adicional.

9.6 Queries mínimas esperadas

  • GetDashboardAttentionItems ou queries menores por widget;
  • GetEventFinancialSummary;
  • GetUpcomingEvents;
  • GetOverdueTasks;
  • GetLeadsWithoutNextAction;
  • GetOverduePayments;
  • GetDueSoonPayments.

9.7 Fluxos técnicos

Briefing

Livewire valida
→ CaptureWebsiteLead
→ Lead salvo em transação
→ LeadActivity criada
→ NewLeadCaptured disparado após commit
→ Database notification e e-mail em fila
→ confirmação exibida

Conversão

Filament Action autoriza
→ ConvertLeadToEvent
→ lock/checagem idempotente
→ cria Event
→ cria checklist
→ atualiza Lead
→ cria atividade e auditoria
→ commit

Pagamento

Filament form valida
→ RecordManualPayment
→ converte string monetária para centavos
→ salva Payment
→ cria auditoria
→ Query financeira recalcula leitura

Publicação de caso

Filament salva conteúdo
→ valida imagem e alt text
→ publica por published_at
→ rota pública passa a exibir
→ sitemap inclui slug

10. Interface Filament

10.1 Resources obrigatórios

  • LeadResource;
  • EventResource;
  • EventTaskResource ou relation manager + visão global;
  • VendorResource;
  • BudgetItemResource preferencialmente dentro do evento;
  • PaymentResource preferencialmente dentro do evento + visão global;
  • DocumentResource ou managers vinculados;
  • ServiceResource;
  • PortfolioCaseResource;
  • TestimonialResource;
  • SiteSettingResource ou página singleton;
  • UserResource;
  • AuditLogResource somente leitura.

10.2 Regras de Resource

  • tabelas sempre paginadas;
  • busca somente em campos úteis;
  • filtros indexados;
  • eager loading explícito para evitar N+1;
  • ações de estado devem chamar Actions;
  • labels e mensagens em pt-BR;
  • valores monetários formatados em BRL;
  • datas apresentadas no timezone do produto;
  • ações destrutivas confirmadas;
  • Policies aplicadas e testadas;
  • campos internos nunca expostos em rotas públicas.

10.3 Dashboard

Widgets devem executar queries pequenas e independentes. Não fazer uma consulta gigante que carregue todos os registros.

10.4 Detalhe do evento

A página deve combinar, sem virar uma única classe monolítica:

  • header do evento;
  • cards de atenção;
  • resumo financeiro;
  • tarefas;
  • fornecedores;
  • documentos;
  • ações rápidas.

Usar componentes/Widgets menores e testáveis.


11. Site público e interatividade

11.1 Estado atual e componentes candidatos

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.

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

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 formulário deve:

  • ter estado tipado ou Form Object quando útil;
  • validar no servidor;
  • possuir loading state;
  • desabilitar botão durante submissão;
  • preservar acessibilidade;
  • limpar dados após sucesso;
  • evitar exposição de exceção;
  • suportar teste de submissão sem navegador (feature test);
  • suportar jornada E2E em navegador real.

11.3 JavaScript

  • manter o site público em JS vanilla progressivo;
  • não introduzir framework SPA;
  • não usar dependência JS quando CSS e HTML resolverem;
  • toda interação crítica deve funcionar sem estado global complexo;
  • Alpine só entra junto com Livewire, se o gatilho de §22 disparar.

12. Segurança e privacidade

12.1 Autenticação

  • login interno;
  • e-mail verificado;
  • reset seguro;
  • senhas tratadas pelo Laravel;
  • cookie secure, httpOnly e sameSite em produção;
  • usuário inativo bloqueado;
  • acesso Filament validado por canAccessPanel ou mecanismo equivalente.

2FA pode ser adicionado apenas se suportado de forma simples pelo stack escolhido. Não bloquear o MVP por isso.

12.2 Autorização

Policies obrigatórias para entidades internas.

Admin:

  • acesso total.

Assistant:

  • operação cotidiana;
  • sem usuários, configurações globais e auditoria;
  • exclusões críticas restritas.

12.3 Formulário público

  • CSRF;
  • rate limit;
  • honeypot;
  • validação server-side;
  • limite de tamanho de campos;
  • normalização de e-mail e telefone;
  • proteção contra mass assignment;
  • logs sem conteúdo integral da mensagem do visitante.

12.4 Uploads

  • allowlist de MIME e extensão;
  • limite de tamanho;
  • path aleatório;
  • arquivos privados por padrão;
  • imagens públicas com validação e alt text;
  • não confiar no nome original;
  • download autorizado por Policy;
  • proteção contra path traversal.

12.5 LGPD

  • coletar apenas dados necessários;
  • exibir aviso de privacidade no briefing;
  • registrar aceite do aviso;
  • não tratar consentimento como base universal;
  • definir rotina administrativa para correção e exclusão quando cabível;
  • evitar dados sensíveis no MVP;
  • não registrar dados pessoais desnecessários em logs ou auditoria;
  • documentar retenção de leads perdidos antes do lançamento.

12.6 Dependências

  • composer.lock e lock de frontend versionados;
  • composer audit no CI;
  • npm audit conforme política definida no projeto;
  • nenhuma dependência abandonada ou sem uso;
  • justificar dependências grandes em PR/ADR.

13. Estratégia de testes

13.1 Objetivo

A pirâmide deve possuir:

  1. muitos testes unitários rápidos;
  2. testes feature/integration suficientes para Laravel, PostgreSQL, Livewire e Filament;
  3. poucos testes E2E cobrindo jornadas críticas;
  4. testes E2E, de acessibilidade, motion e smoke nas jornadas públicas mais importantes.

A distribuição é por intenção, não por percentual rígido.

13.2 Unit tests

Não inicializam Laravel nem banco quando possível.

Cobertura obrigatória:

  • conversão e formatação de dinheiro;
  • rejeição de valores negativos;
  • status derivado de pagamento;
  • cálculo de totais financeiros;
  • transições de lead;
  • invariantes de conversão;
  • conclusão e reabertura de tarefa;
  • cálculo de vencimento;
  • regras de publicação quando extraídas para domínio.

Exemplo esperado:

it('marks an unpaid past-due payment as overdue', function () {
    $payment = PaymentSchedule::from(
        amount: new Money(150000),
        dueDate: new DateTimeImmutable('2026-07-01'),
        paidAt: null,
    );

    expect($payment->statusAt(new DateTimeImmutable('2026-07-27')))
        ->toBe(PaymentStatus::Overdue);
});

13.3 Feature e integration tests

Devem inicializar Laravel e usar PostgreSQL real no CI.

Cobertura obrigatória:

  • migrations e constraints;
  • Actions;
  • Policies;
  • conversão transacional e idempotente;
  • criação de checklist;
  • validação do briefing;
  • notificações;
  • upload e autorização de download;
  • queries financeiras;
  • filtros principais;
  • Resources e Actions Filament;
  • componentes Livewire;
  • publicação e despublicação de conteúdo;
  • autenticação e papéis.

Usar Mail::fake, Notification::fake, Storage::fake e Queue::fake quando o objetivo não for testar a integração externa.

13.4 E2E browser

Executar com Chromium headless contra a aplicação servida por FrankenPHP.

Jornadas obrigatórias:

ID Jornada Resultado esperado
E2E-01 Visitante envia briefing Lead criado, sucesso visível, sem erro de console
E2E-02 Assessora autentica e trata lead Login, filtro, status e próxima ação funcionam
E2E-03 Assessora converte lead Evento e checklist criados uma única vez
E2E-04 Assessora registra orçamento e pagamento Totais atualizados e pagamento visível
E2E-05 Assessora publica caso Conteúdo aparece na rota pública

Não duplicar todas as combinações no browser. Casos de borda ficam em unit/feature.

Em falha, CI deve publicar:

  • screenshot;
  • trace ou vídeo quando suportado;
  • logs da aplicação;
  • logs do browser;
  • HTML report quando disponível.

13.5 Testes de arquitetura

Criar regras Pest Architecture:

arch()
    ->expect('App\\Domain')
    ->toUseStrictTypes()
    ->not->toUse(['dd', 'dump', 'die']);

arch()
    ->expect('App\\Domain')
    ->not->toDependOn(['App\\Filament', 'App\\Livewire']);

Adicionar regras conforme a estrutura real, sem tornar a suíte excessivamente frágil.

13.6 Cobertura

  • meta de 80% para Domain e Application;
  • não medir views, migrations, código gerado e framework;
  • cobertura não substitui critérios de aceite;
  • queda de cobertura em módulo crítico deve bloquear merge.

13.7 Acessibilidade automatizada

Smoke/browser tests devem verificar:

  • ausência de issues críticas ou sérias;
  • foco inicial coerente quando modal abrir;
  • labels de formulário;
  • landmarks e headings básicos;
  • ausência de erro de console.

Revisão manual mínima antes do lançamento:

  • navegação por teclado;
  • foco visível;
  • contraste;
  • zoom a 200%;
  • leitor de tela nos fluxos de briefing e login.

13.8 Comandos padronizados

O projeto deve expor scripts equivalentes:

composer test:unit
composer test:feature
composer test:browser
composer test
composer quality

Composição esperada:

test:unit      → Unit + Architecture
test:feature   → Feature + Livewire + Filament
test:browser   → E2E + acessibilidade + motion + smoke
quality        → Pint check + PHPStan/Larastan + audits + testes

14. CI/CD

14.1 Gates de pull request

Job Responsabilidade Bloqueia merge
static Pint, PHPStan/Larastan, Composer validate, Composer e npm audit Sim
unit Unitários, arquitetura e cobertura Sim
feature PostgreSQL, migrations, Livewire, Filament e integração Sim
browser Vite, FrankenPHP, E2E, smoke, acessibilidade e motion Sim
container Build da imagem final e healthcheck Sim

14.2 Regras do pipeline

  • todo PR executa todos os gates;
  • usar cache de Composer, npm e browser de forma segura;
  • banco de integração deve ser PostgreSQL;
  • CI não deve usar SQLite como substituto;
  • browser tests usam o mesmo artefato ou imagem próxima da produção;
  • falhas devem publicar artefatos diagnósticos;
  • migrations devem ser executadas em banco vazio;
  • seed de demonstração deve ser executável;
  • secrets nunca ficam no repositório ou na imagem.

14.3 Branches e ambientes

  • PR: testes e preview opcional;
  • main: build imutável por SHA publicado no registry Gitea (git.hellomanoel.com) e deploy automático em staging via Dokploy;
  • 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 (retag do digest em :production);
  • produção requer aprovação humana explícita no MVP (workflow_dispatch com confirmação);
  • rollback usa imagem anterior (SHA anterior, sem rebuild);
  • migrations devem ser backward-compatible quando possível.

14.4 Definition of Done

Uma história só está concluída quando:

  • critérios de aceite estão atendidos;
  • código passa por Pint;
  • PHPStan/Larastan está verde;
  • unit e feature tests cobrem regras relevantes;
  • E2E foi criado ou atualizado para fluxo crítico;
  • acessibilidade automatizada não possui issues críticas/sérias;
  • migration foi testada;
  • autorização foi verificada;
  • logs não expõem PII desnecessária;
  • factories e seed foram atualizados;
  • staging e smoke pós-deploy estão verdes;
  • documentação afetada foi atualizada.

15. Deploy com FrankenPHP

15.1 Decisão

Usar FrankenPHP em modo regular no MVP.

NÃO ativar worker mode inicialmente.

Worker mode somente poderá ser ativado após:

  • profiling demonstrar benefício relevante;
  • testes de persistência de estado;
  • testes de memória;
  • suíte de regressão verde;
  • ADR aprovada.

15.2 Processos

Processo Imagem Comando/função
web imagem da aplicação FrankenPHP/Caddy servindo public/
queue mesma imagem php artisan queue:work --sleep=2 --tries=3
scheduler mesma imagem php artisan schedule:work ou cron schedule:run
database serviço gerenciado PostgreSQL com backup
files serviço gerenciado bucket S3-compatible

15.3 Dockerfile

Usar multi-stage build:

  1. Composer dependencies;
  2. frontend assets;
  3. runtime FrankenPHP.

Requisitos:

  • versão PHP fixada;
  • extensões PHP explícitas;
  • composer install --no-dev --prefer-dist --no-interaction --classmap-authoritative em produção;
  • npm ci;
  • build Vite;
  • usuário não-root quando suportado;
  • nenhum secret em layer;
  • healthcheck;
  • imagem reproduzível;
  • caches Laravel criados no entrypoint/deploy quando dependem do ambiente.

Não executar php artisan config:cache em uma stage que não possui as variáveis finais quando isso congelar configuração incorreta.

15.4 Variáveis de ambiente mínimas

APP_NAME
APP_ENV
APP_KEY
APP_DEBUG=false
APP_URL
APP_LOCALE=pt_BR
APP_FALLBACK_LOCALE=pt_BR
APP_TIMEZONE=America/Sao_Paulo

DB_CONNECTION=pgsql
DB_HOST
DB_PORT
DB_DATABASE
DB_USERNAME
DB_PASSWORD

CACHE_STORE=database ou file conforme ambiente
QUEUE_CONNECTION=database
SESSION_DRIVER=database ou cookie conforme decisão

FILESYSTEM_DISK=r2 em produção
R2_ACCESS_KEY_ID
R2_SECRET_ACCESS_KEY
R2_BUCKET
R2_ENDPOINT
R2_URL (domínio próprio 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=resend em produção (mailer nativo Laravel)
RESEND_API_KEY
MAIL_FROM_ADDRESS
MAIL_FROM_NAME

15.5 Healthcheck

GET /up deve:

  • responder rapidamente;
  • não exigir autenticação;
  • não expor segredo;
  • retornar falha quando a aplicação não inicializar;
  • opcionalmente validar conexão simples com banco em check separado, sem tornar o endpoint caro.

16. Observabilidade, backup e operação

16.1 Logs

Logs estruturados devem incluir quando disponível:

  • request ID;
  • user ID;
  • rota;
  • ação;
  • tipo e ID de entidade;
  • duração;
  • nível e exceção.

Não registrar:

  • senha;
  • token;
  • conteúdo integral de comprovante;
  • conteúdo integral de mensagem pessoal;
  • dados pessoais sem necessidade.

16.2 Monitoramento mínimo

  • disponibilidade da home;
  • disponibilidade do briefing;
  • disponibilidade do login;
  • erros não tratados;
  • falhas repetidas de queue;
  • falha de backup;
  • smoke pós-deploy.

Não construir stack própria de observabilidade distribuída no MVP.

16.3 Backup

Item Política inicial
PostgreSQL backup diário automático
Retenção mínimo 14 dias
Arquivos versionamento ou lifecycle do bucket
RPO até 24 horas
RTO até 4 horas
Teste de restauração trimestral

O procedimento de restauração deve ser documentado antes da produção.


17. Seeds, factories e dados determinísticos

17.1 Factory obrigatória

Criar factories para:

  • User;
  • Lead;
  • LeadActivity;
  • Event;
  • EventTask;
  • Vendor;
  • EventVendor;
  • BudgetItem;
  • Payment;
  • Service;
  • PortfolioCase;
  • Testimonial;
  • Document, quando viável sem arquivo real.

17.2 Seed de demonstração

O seed deve criar:

  • um admin;
  • um assistant;
  • configurações do site;
  • 3 serviços;
  • 3 casos de portfólio;
  • 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;
  • 2 eventos futuros e 1 concluído;
  • tarefas vencidas e futuras;
  • fornecedores;
  • itens de orçamento;
  • pagamentos pagos, pendentes e vencidos.

As credenciais de desenvolvimento devem ser documentadas apenas em ambiente local e nunca usadas em produção.

17.3 Determinismo

Para visual e browser tests:

  • usar datas fixas;
  • usar imagens fixture versionadas ou placeholders estáveis;
  • não depender de rede externa;
  • não usar conteúdo randômico não seedado;
  • congelar horário.

18. Backlog de implementação

Recorte vigente (ADR-016). Fases 0 e 1 são o escopo do lançamento e estão concluídas. Fases 2 a 5 estão adiadas, sem data. Não iniciar nenhuma delas sem uma decisão nova do responsável pelo produto — a §1.1 manda trabalhar uma fase por vez, e a fase corrente é o acabamento e a publicação do site.

O agente deve implementar na sequência, salvo instrução explícita.

Fase 0 — Fundação

Entregas:

  • projeto Laravel;
  • PostgreSQL local e CI;
  • Filament instalado e autenticado;
  • Livewire configurado;
  • Tailwind/Vite;
  • FrankenPHP e Docker Compose local;
  • papéis admin/assistant;
  • Pint;
  • PHPStan/Larastan;
  • Pest;
  • Pest Browser;
  • Architecture tests;
  • pipeline CI inicial;
  • design tokens mínimos;
  • healthcheck;
  • 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) — run 31395107465 em 7e68c0e, com Dokploy deployment succeeded e smoke verde em /up, / e /admin/login.

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.

Fase 1 — Site e CMS

  • site_settings;
  • serviços;
  • portfólio e galeria;
  • depoimentos;
  • home;
  • listagem e detalhe de serviços;
  • listagem e detalhe de portfólio;
  • sobre;
  • privacidade;
  • SEO;
  • mídia otimizada;
  • testes de acessibilidade.

Critério de saída: conteúdo gerenciável no Filament, testes browser funcionais, de acessibilidade e motion aprovados, e revisão humana do site público no PR.

Fase 2 — Leads — ADIADA (ADR-016)

  • migration/model/factory de Lead;
  • LeadActivity;
  • briefing Livewire;
  • proteção contra abuso;
  • notificação de novo lead;
  • LeadResource;
  • filtros;
  • próxima ação;
  • histórico;
  • perda e reabertura;
  • testes unit/feature/browser;
  • E2E-01 e E2E-02.

Critério de saída: jornada visitante → lead → tratamento interna totalmente verde.

Fase 3 — Eventos e tarefas — ADIADA (ADR-016)

  • Event;
  • EventTask;
  • conversão idempotente;
  • checklist padrão;
  • EventResource;
  • detalhe customizado;
  • tarefas por evento;
  • visão global de tarefas;
  • dashboard operacional inicial;
  • E2E-03.

Critério de saída: lead é convertido e evento pode ser administrado.

Fase 4 — Fornecedores e financeiro — ADIADA (ADR-016)

  • Vendor;
  • EventVendor;
  • BudgetItem;
  • Payment;
  • Money/conversão para centavos;
  • resumo financeiro;
  • pagamentos pagos, pendentes e vencidos;
  • comprovante opcional;
  • auditoria financeira;
  • widgets financeiros;
  • E2E-04.

Critério de saída: assessora acompanha orçamento e pagamentos sem integração bancária.

Fase 5 — Documentos, hardening e lançamento — ADIADA (ADR-016)

  • documentos privados;
  • auditoria completa;
  • scheduler de resumo;
  • performance e índices;
  • revisão N+1;
  • revisão de Policies;
  • revisão LGPD;
  • backup e restore documentados;
  • monitoramento;
  • smoke pós-deploy;
  • revisão manual de acessibilidade;
  • E2E-05;
  • seed de demonstração completo;
  • documentação operacional.

Critério de saída: Definition of Done integral e produção aprovada.


19. Critérios de aceite transversais

Toda tela interna deve:

  • exigir autenticação;
  • aplicar Policy;
  • estar em pt-BR;
  • exibir estados vazios úteis;
  • possuir validação server-side;
  • indicar sucesso e falha;
  • ser navegável por teclado;
  • não executar N+1 conhecido;
  • paginar listas de crescimento aberto;
  • possuir teste proporcional ao risco.

Toda rota pública deve:

  • funcionar sem autenticação;
  • não expor conteúdo não publicado;
  • possuir title e description;
  • usar layout responsivo;
  • não emitir erro de console;
  • respeitar acessibilidade básica;
  • ter comportamento de erro seguro.

Toda operação financeira deve:

  • usar centavos inteiros;
  • ser validada;
  • ser autorizada;
  • gerar auditoria quando crítica;
  • possuir testes unitários e feature.

20. Riscos e mitigação

Risco Mitigação obrigatória
Filament concentrar domínio Resources finos, Actions e Queries testáveis
Site parecer genérico design tokens, conteúdo real, fotografia e revisão humana
Escopo crescer lista de não objetivos e mudança somente com hipótese real
Financeiro virar contabilidade limitar a orçamento e pagamentos manuais
Worker mode vazar estado manter modo regular até benchmark e ADR
Upload degradar performance limites, variantes, storage externo
SQLite esconder diferenças PostgreSQL em integração e CI
Regras escondidas em callbacks Actions explícitas e testes de caso de uso
Dashboard ficar lento queries independentes, índices e agregações pequenas

21. ADRs iniciais

ADR Decisão Status
ADR-001 Monólito modular Laravel, sem microserviços 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-004 Pagamentos somente manuais Aceita
ADR-005 Pest unifica unit, feature e browser Aceita
ADR-006 FrankenPHP regular mode; worker mode adiado Aceita
ADR-007 Single-tenant; SaaS e portal do cliente adiados Aceita
ADR-008 Database queue; Redis adiado 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-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 registry Gitea 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
ADR-016 Lançamento de 31/08/2026 entrega apenas o site institucional (Fases 01); Fases 25 seguem especificadas e adiadas, sem data Aceita

22. Gatilhos objetivos para evolução

Evolução Gatilho
Portal do cliente clientes pedem repetidamente visibilidade e aprovação fora do WhatsApp
RSVP volume relevante de eventos exige gestão de convidados
Pagamento online cobrança manual causa esforço ou inadimplência mensurável
Multi-tenancy uma segunda assessoria aceita pagar e usar o produto
Redis database queue não atende volume ou confiabilidade
FrankenPHP worker benchmark prova ganho e testes de estado/memória passam
API pública existe consumidor real e contrato de integração
Kanban tabela de leads demonstra limitação frequente observada
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

23. Condições de conclusão do MVP

O MVP está concluído somente quando:

A ADR-016 divide estas condições em dois recortes. Cada um se fecha por conta própria; o segundo não bloqueia o lançamento.

23.1 Lançamento do site (Fases 01)

O lançamento está concluído somente quando:

  • site público está publicado e visualmente aprovado;
  • assessora edita os conteúdos essenciais sem desenvolvedor;
  • briefing envia o pedido de proposta de forma segura, com proteção contra abuso e aceite de privacidade registrado;
  • usuários e Policies estão corretos;
  • testes unit, feature, browser funcionais e arquitetura estão verdes;
  • CI bloqueia regressões;
  • imagem FrankenPHP é reproduzível;
  • staging e produção usam a mesma imagem promovida;
  • backup, restauração e monitoramento estão documentados;
  • nenhum item explicitamente fora do MVP (§4.2) foi introduzido.

Note a diferença em relação à versão anterior desta seção: o critério do briefing é enviar o pedido, não "criar leads". Criar Lead é Fase 2 e está adiado; o formulário atual envia e-mail e não persiste nada.

23.2 Produto completo (Fases 25, adiado)

Além de tudo em §23.1:

  • pipeline e próxima ação funcionam;
  • briefing cria leads de forma segura e persistente;
  • lead é convertido uma única vez em evento;
  • checklist é criado automaticamente;
  • evento possui visão consolidada;
  • fornecedores podem ser cadastrados e vinculados;
  • orçamento e pagamentos manuais possuem totais consistentes;
  • dashboard mostra pendências do dia;
  • auditoria registra operações críticas;
  • jornadas E2E das fases correspondentes estão verdes.

24. Formato esperado de reporte do agente

Ao finalizar uma tarefa, o agente deve responder no formato:

Requisito implementado: <ID e nome>

Alterações:
- <arquivo ou módulo>
- <arquivo ou módulo>

Testes adicionados/atualizados:
- <teste>
- <teste>

Comandos executados:
- <comando e resultado>

Critérios de aceite:
- [x] <critério>
- [x] <critério>

Pendências ou desvios:
- Nenhum

Caso exista desvio:

Desvio da SPEC:
- Decisão afetada:
- Motivo:
- Alternativa escolhida:
- Impacto:
- ADR criada/atualizada:

25. Primeira instrução recomendada ao agente

Leia integralmente o SPEC.md e inspecione o repositório. Implemente apenas a Fase 0 — Fundação. Antes de alterar arquivos, apresente um plano curto relacionando cada mudança aos requisitos da fase. Não avance para a Fase 1. Ao terminar, execute todos os gates disponíveis, reporte os resultados e marque somente os itens comprovadamente concluídos.