Pular para o conteúdo

9. Exemplo de ADR (000) · versão 2.0.0

003 — Plan · Módulo de Tarefas (EXEMPLO)

manifesto/04-templates/000-exemplo-modulo-tarefas/003-plan.md

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 Task no schema do Prisma (prisma/models/tasks.prisma).
  • O domínio tasks entra no OpenAPI e no Scalar (/reference).
  • Estabelece o padrão de store que os próximos domínios seguirão.

Tarefas

  • T1 — Model Task no Prisma + migration
  • T2 — Schemas Zod, contrato OpenAPI e testes da rota (vermelho)
  • T3 — Rotas GET/POST /api/tasks e PATCH /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 id e 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) useState no 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.