Pular para conteúdo

Implementation Plan: Fechamento das Lacunas Pós-Migração

Branch: 003-post-migration-gaps | Date: 2026-08-10 | Spec: spec.md

Input: Feature specification from specs/003-post-migration-gaps/spec.md

Summary

Restaurar o calendário visual usando o contrato de agendamentos já existente, mover conexões OAuth para /calendar/settings e criar um resumo autenticado do dashboard. Pacientes ativos e consultas de hoje serão agregados no PostgreSQL por owner e fuso. Documentos e receita terão estado explícito unavailable porque o schema atual não possui fontes persistidas e auditáveis. CEP, CNPJ e CFP serão encerrados neste ciclo por um ADR de produto; uma decisão de adoção abrirá outra feature antes de qualquer integração.

Technical Context

Language/Version: TypeScript 5.9; Bun 1.3 na API; Node.js 22 no web.

Primary Dependencies: Elysia 1.4, Drizzle ORM 0.45 e TypeBox na API; Next.js 15.4, React 19, TanStack Query 5, date-fns 4, lucide-react e shadcn/ui no web.

Storage: PostgreSQL existente. Nenhuma migration é necessária para calendário ou resumo; a decisão externa é documentada em Markdown.

Testing: Bun unit/integration tests na API; TypeScript typecheck e Next.js build no web; Playwright para browser → API → PostgreSQL.

Target Platform: Navegadores modernos responsivos; containers Linux nos deploys separados de web e API.

Project Type: Aplicação web e serviço REST em repositórios isolados dentro do workspace de migração.

Performance Goals: p95 menor que 200 ms nas leituras REST de calendário e resumo com dados de validação; resultado visual utilizável em até 2 segundos; interações locais da grade sem bloqueio perceptível.

Constraints: Ownership individual obrigatório; resposta do dashboard calculada em um único referenceAt; datas persistidas como instantes e agrupadas pelo fuso IANA validado; nenhum conteúdo clínico em eventos; estados unavailable não podem virar zero; sem nova integração externa ou segredo nesta feature.

Scale/Scope: Duas rotas web, um endpoint novo, extensão do cliente tipado, componentes de calendário, testes API/E2E e um ADR de três decisões. O limite inicial de consulta do calendário é de 42 dias por requisição.

Constitution Check

Pre-design gate

Gate Status Evidence
Specification before implementation PASS spec.md contém escopo, fora de escopo, erros, critérios e aguarda aprovação do owner.
Contract-first boundaries PASS O plano produz contratos separados de dashboard, calendário/UI e decisão externa antes das tarefas.
Vertical slice verification PASS quickstart.md cobre API, banco, browser, mobile e teclado com dados determinísticos.
Clinical data safety PASS Todas as consultas filtram ownerUserId; eventos não carregam conteúdo clínico; erros não revelam outro owner.
Legible structure PASS A feature reutiliza domínios existentes, não adiciona serviço/repositório e explicita métricas indisponíveis.
Product constraints PASS Next.js/pnpm, Bun/Elysia, shadcn/ui e pt-BR são preservados; sem migration ou deploy change.

Post-design re-check

PASS. Os contratos cobrem sucesso, validação, autenticação, indisponibilidade e isolamento. Não há violação que exija Complexity Tracking. A implementação permanece bloqueada até aprovação do owner.

Project Structure

Documentation (this feature)

specs/003-post-migration-gaps/
├── checklists/requirements.md
├── contracts/
│   ├── calendar-ui.md
│   ├── dashboard-summary.openapi.yaml
│   └── external-lookups-decision.md
├── data-model.md
├── plan.md
├── quickstart.md
├── research.md
├── spec.md
└── tasks.md

Source Code (repository root)

prontuare-api/
├── src/
│   ├── domains/
│   │   ├── calendar/{calendar.routes.ts,calendar.service.ts}
│   │   └── dashboard/{dashboard.routes.ts,dashboard.service.ts}
│   └── main.ts
└── test/{calendar.integration.test.ts,dashboard.integration.test.ts}

prontuare-web/
├── app/(dashboard)/
│   ├── calendar/{page.tsx,settings/page.tsx}
│   └── page.tsx
├── components/calendar/
│   ├── calendar-grid.tsx
│   ├── calendar-toolbar.tsx
│   ├── month-view.tsx
│   ├── week-view.tsx
│   └── agenda-list.tsx
├── lib/{api.ts,calendar.ts}
└── tests/{calendar-dashboard.spec.ts,fixtures/post-migration.ts}

Structure Decision: Preservar os dois deployables. O dashboard recebe domínio próprio na API porque agrega dados de vários domínios sem transferir regras de contagem ao web. A grade fica em componentes locais no web e reutiliza /api/appointments. Integrações OAuth são movidas, não duplicadas.

Delivery Design

Slice 1 — Calendar visual (MVP)

  1. Endurecer o contrato de listagem com intervalo máximo, ordenação determinística e identificação segura do paciente.
  2. Implementar cálculo de intervalos e layout mensal/semanal sem nova biblioteca de calendário.
  3. Mover a página atual para /calendar/settings e manter callbacks OAuth direcionados a ela.
  4. Validar navegação, sobreposição, cancelamento, mobile/lista, teclado e isolamento.

Slice 2 — Dashboard summary

  1. Adicionar GET /api/dashboard/summary com referenceAt e timezone.
  2. Agregar pacientes e consultas no banco; responder documentos e receita como unavailable com códigos estáveis.
  3. Substituir quatro queries/valores dispersos por uma única query no web.
  4. Validar limites de dia/mês, falha, retry, cache e isolamento.

Slice 3 — External lookup governance

  1. Auditar o comportamento local existente e distinguir máscara/formatação de consulta externa real.
  2. Preencher e aprovar uma decisão por CEP, CNPJ e CFP.
  3. Remover promessas incorretas da UI se a decisão for aposentar/adiar; adoção abre feature independente.

Risks and Mitigations

Risk Mitigation
Contagem de “hoje” divergir por fuso/DST Validar timezone IANA, calcular limites uma vez a partir de referenceAt e testar bordas.
Grade expor nome de paciente além do necessário Contrato retorna somente identificação mínima; nenhum dado clínico.
Calendário mensal disparar consultas excessivas Intervalo máximo de 42 dias e chave de cache por from, to, timezone e view.
Callback OAuth voltar à grade e perder feedback Redirecionar callback para /calendar/settings e testar sucesso/cancelamento.
Cards indisponíveis parecerem zero União discriminada available/unavailable; UI nunca formata valor ausente.
Consulta CEP/CNPJ atual ser confundida com validação confiável ADR e UI distinguem auto-preenchimento, validação e entrada manual.

Rollout and Rollback

  • Entregar calendário e dashboard como mudanças independentes, sem migration.
  • Antes do deploy, executar testes API, typecheck/build dos dois serviços e Playwright real.
  • Rollback do web restaura a página de conexões em /calendar; rollback da API remove somente o registro de rota do dashboard.
  • O endpoint novo é aditivo. O cliente web só deve depender dele depois de API compatível estar publicada.
  • Nenhum código legado em apps/ será removido nesta entrega.