9. Exemplo de ADR (000) · versão 2.0.0
003 — Plan · Módulo de Tarefas (EXEMPLO)
Data: 2026-05-20
Contexto
A equipe precisa de um módulo simples de tarefas internas. O foco é validar o fluxo da ADR com um escopo enxuto, na stack universal (Next.js App Router, Prisma, Zod, OpenAPI e Scalar, Zustand, Vitest).
Decisão
Construir o domínio tasks com criar, listar, concluir e arquivar, e filtro por situação. Contrato
primeiro: schemas Zod em app/server/tasks/schemas.ts, que geram o trecho do OpenAPI; rotas de um
arquivo só, com Prisma direto (sem service, enquanto uma rota só usa cada regra). Estado no
frontend na store stores/tasks/ (store.ts + sync.tsx).
Consequências
- Surge a tabela
Taskno schema do Prisma (prisma/models/tasks.prisma). - O domínio
tasksentra no OpenAPI e no Scalar (/reference). - Estabelece o padrão de store que os próximos domínios seguirão.
Tarefas
- T1 — Model
Taskno Prisma + migration - T2 — Schemas Zod, contrato OpenAPI e testes da rota (vermelho)
- T3 — Rotas
GET/POST /api/tasksePATCH /api/tasks/{id}(verde), com escopo do dono - T4 — Store
stores/tasks/(store + sync) e a tela de lista com filtro - T5 — Smoke do domínio
tasks
Quiz de decisões
Formato:
( )alternativa avaliada ·(X)escolhida. Alternativas descartadas permanecem como memória técnica — o que é certo está marcado; o resto é o que foi rejeitado e por quê.
Tema: Dados
P1. Como tratar a exclusão de tarefas?
- ( ) A) Exclusão física (
DELETE) ❌ rejeitada: perde o histórico - (X) B) Arquivamento lógico (campo
archivedAt) ✅ — preserva o histórico sem custo extra - ( ) C) Tabela de lixeira separada ❌ rejeitada: complexidade sem necessidade
Justificativa: o arquivamento lógico atende o requisito sem estrutura nova.
P2. Situação da tarefa: enum no banco ou texto livre?
- (X) A) Enum (
OPEN/DONE/ARCHIVED) ✅ — integridade e tipagem - ( ) B) Texto livre ❌ rejeitada: quebra a tipagem total (princípio 6)
Tema: API
P3. Validação e contrato?
- (X) A) Zod em toda entrada e saída, com o OpenAPI gerado dos mesmos schemas ✅ (princípio 7)
- ( ) B) Validar só no frontend ❌ rejeitada: nunca confiar no cliente
P4. Quem vê qual tarefa?
- (X) A) Cada pessoa vê só as suas:
where: { id, ownerId: session.userId }no próprio Prisma ✅ - ( ) B) Buscar pelo
ide conferir o dono depois ❌ rejeitada: é o caminho do IDOR (Segurança)
P5. Uma rota para “concluir” ou o PATCH da tarefa?
- (X) A)
PATCH /api/tasks/{id}com{ status }✅ — menos superfície, o mesmo schema - ( ) B)
POST /api/tasks/{id}/complete❌ rejeitada: rota a mais sem regra própria
Tema: Frontend
P6. Onde mora o estado da lista?
- (X) A) Store Zustand
stores/tasks/(store.ts + sync.tsx) ✅ — padrão obrigatório - ( ) B)
useStateno componente ❌ rejeitada: lógica de negócio não vive em componente
Tema: Testes
P7. Estratégia de teste?
- (X) A) Testes da rota contra o contrato antes da implementação + smoke do domínio ✅
- ( ) B) Só teste manual ❌ rejeitada: desenvolvimento guiado a testes (princípio 8)
Pós-plan
Riscos: baixo — escopo pequeno, sem integrações.
Dependências: a primeira migration do projeto.
Fora de escopo: etiquetas, prioridade, notificações, permissões finas.
Critério de aceite: criar, listar, concluir e arquivar funcionando, filtro por situação, a outra
pessoa não vê a tarefa de ninguém (404), smoke verde, pnpm lint, typecheck, test e build
passando.