Pular para o conteúdo principal

Status: Approved · v1 · SPEC-DELIVERY-MOCK-API-MIGRATION-001

depends_on: SPEC-ARCH-QUALITY-001

used_by: IS-MVP-15.1

Checklist de migração Mock→API

Como uma superfície (ambiente ou app) passa de mocks para a API real sem drift de contrato, e como isso é verificado.

O mecanismo de troca

A troca entre mock e API real é por client, no boot do app — nunca por tela. packages/shared/src/clients/client-config.ts#createHttpClient{NEXT_PUBLIC,EXPO_PUBLIC}_USE_MOCKS uma única vez e devolve ou um MockClient (@raizfc/mocks) ou um ApiClient real, ambos implementando a mesma interface HttpClient. apps/web/src/shared/http-client.ts e apps/mobile/src/shared/http-client.ts instanciam esse client uma vez por app (httpClient, singleton de módulo) e todo hook/serviço o consome — nenhuma tela importa @raizfc/mocks ou monta fetch diretamente. assertClientConfig recusa mocks habilitados quando environment === 'production', então não existe caminho de build/runtime em que produção sirva dado mockado.

Checklist para religar uma superfície à API real

Ao trocar USE_MOCKS=truefalse para um ambiente (staging, produção) ou ao decidir que um domínio específico está pronto para sair do preview mockado:

  • {PREFIX}_API_BASE_URL aponta para uma API real acessível a partir do client (CORS, HTTPS).
  • pnpm run validate:contract-parity está verde contra essa API — ver seção seguinte.
  • pnpm run build com NODE_ENV=production e {PREFIX}_USE_MOCKS=false compila sem o guard de assertClientConfig disparar (client-config.ts).
  • Os smoke P0 de SPEC-ARCH-QUALITY-001 (/feed, /search, /matches, /teams/:slug, /players/:slug, /matches/:id, /championships/:slug, /management, /profile) foram exercitados manualmente contra a API real pelo menos uma vez antes do primeiro deploy.
  • Nenhum dado sensível (ver SPEC-ARCH-SECURITY-001 — checklist por endpoint) aparece em um DTO público que só deveria existir no lado autenticado/gestão.
  • Rollback: reverter {PREFIX}_USE_MOCKS para true é suficiente para voltar ao preview mockado — nenhuma migração de estado é necessária porque mock e API real nunca compartilham storage.

Contract parity — o que é verificado automaticamente

tests/contract-parity/contract-parity.test.mjs (pnpm run validate:contract-parity) chama o mesmo request contra um MockClient e uma instância real da API (services/api compilado, em processo) e compara a forma da resposta — o conjunto de caminhos de chave e o tipo primitivo de cada folha, nunca o valor literal (meta.requestId/meta.timestamp são gerados por request e nunca serão idênticos byte a byte entre os dois lados). Isso prova exatamente a garantia que uma tela depende: o DTO que ela recebe tem a mesma forma não importa qual HttpClient o app escolheu no boot.

Cobertura: os nove smoke P0 de SPEC-ARCH-QUALITY-001, mais os domínios de maior prioridade que a mesma spec lista (auth/permission/privacy, financial/idempotency, match/result/report/ranking) — login real, GET /auth/me, GET /management/my-entities, carteira do time, cheer idempotente, acesso anônimo negado a gestão. Não é uma enumeração exaustiva de todos os ~28 módulos da API; cada domínio já tem sua própria paridade dupla verificada independentemente por packages/mocks/test/** (282 testes) e services/api/test/** (215 testes), cada lado validado contra packages/contracts. Este suite root-level cobre a lacuna que nenhum dos dois lados sozinho prova: que os dois lados concordam entre si.

Achados corrigidos por esta verificação (EP-MVP-15.1)

A primeira execução deste suite encontrou e corrigiu drift real de fixture/funcionalidade entre mock e API (nenhum dos dois "errado" por si só — apenas desalinhados um do outro):

  • GET /matches/:idheadToHead da API tinha só 1 de 2 confrontos que o mock já tinha.
  • GET /championships/:slugbracket da API tinha só 1 de 2 partidas de quartas e não tinha o item "Semifinal" (vazio) que o mock já tinha.
  • GET /torcidas/:slug e GET /fields/:slugmatches da API não incluía a partida já encerrada (match_last_001) que o mock já incluía.
  • GET /services/:slugshowcase da API não incluía o segundo item (com href) que o mock já incluía.
  • GET /matches — a API não suportava page/pageSize nem devolvia meta.pagination, apesar de o mock já implementar paginação real (SPEC-ARCH-PERF-001 "listas são paginadas"); implementado em MatchesApplicationService#listMatches reaproveitando attachPaginationMeta (o mesmo helper que search já usa) — mesmos defaults do mock (page=1, pageSize=20, máximo 100, valor inválido cai para o default em vez de rejeitar a request, já que o endpoint é público/soft-auth).

Divergência registrada, não corrigida nesta pack

context.error('VALIDATION_ERROR', { message }) no lado mock (usado em ~22 pontos de 13 arquivos de handler, não específico de um domínio) coloca a mensagem específica em error.details.message e deixa error.message com o texto genérico do catálogo (errorMessages[code]); a API real coloca a mesma mensagem específica diretamente em error.message e nunca popula details nesse caso. Ambas as formas são válidas para o contrato (ApiError.message: string, details?: Record<string, unknown>) e nenhum teste existente depende de details.message, então isso não bloqueia o release — mas um pack futuro que tocar o helper genérico de erro dos mocks (createMockErrorResponse) deveria decidir se alinha os ~22 call sites para colocar a mensagem específica em message como a API já faz, em vez de duplicá-la em details.

Não coberto por este checklist

  • Calibração de performance real (latência, N+1) — SPEC-ARCH-PERF-001/IS-MVP-15.3.
  • Auditoria de permissão/IDOR sistemática além do que os testes por domínio já cobrem — SPEC-ARCH-SECURITY-001/IS-MVP-15.2.
  • Escolha de provider real (Pix, storage) — segue condicionada per SPEC-DELIVERY-READINESS-001.