Skip to content

feat(contracts): schemas Zod, erro 422 unificado e versionamento v1/v2 para Edge Functions#84

Closed
adm01-debug wants to merge 1 commit into
mainfrom
claude/webhook-contract-tests-9lJDT
Closed

feat(contracts): schemas Zod, erro 422 unificado e versionamento v1/v2 para Edge Functions#84
adm01-debug wants to merge 1 commit into
mainfrom
claude/webhook-contract-tests-9lJDT

Conversation

@adm01-debug
Copy link
Copy Markdown
Owner

@adm01-debug adm01-debug commented May 22, 2026

Sumário

Estabelece uma camada compartilhada de contratos para Edge Functions:

  • Fonte única de schemas Zod em supabase/functions/_shared/contracts/<endpoint>.contracts.ts (18 arquivos)
  • Shape único de erro de validação 422 { code, message, fields: [{ path, code, message }] } via _shared/contracts/error-response.ts
  • Versionamento via header X-Contract-Version com headers automáticos Deprecation: true + Sunset: <ISO> (RFC 8594), exercitado em product-webhook v1 (deprecated, sunset 2026-08-22) ↔ v2 (stable, price → {amount,currency})
  • Inventory gate de CI que falha se uma Edge Function nova for adicionada sem contrato nem entrada explícita na allowlist (61 funções na allowlist hoje, dívida explícita)

⚠️ Breaking change documentado

Antes (uso heterogêneo): 400 { error: "Validation failed", details: {...fieldErrors} }.
Agora: 422 { code: "VALIDATION_FAILED", message, fields: [...] }.
Status 400 fica reservado para INVALID_JSON, MISSING_BODY, UNSUPPORTED_VERSION (input malformado, não validação semântica).

Verificado via grep que o frontend não consome a forma antiga (.details.fieldErrors, error === 'Validation failed').

Escopo

17 handlers refatorados (lógica de negócio inalterada; schemas movidos para _shared/contracts/):

product-webhook, webhook-dispatcher, webhook-inbound (envelope), ai-recommendations, visual-search, semantic-search, generate-ad-prompt, categories-api, commemorative-dates, analyze-logo-colors, sync-quote-bitrix, quote-sync, generate-product-seo, materials-api, kit-identity-suggest, dropbox-list, magic-up-score, external-db-inspect, generate-ad-image, rate-limit-check.

As demais 61 Edge Functions (sem validação prévia) entram na allowlist tests/contract/_allowlist/no-contract.json — o inventory gate força que cada adição futura seja decisão deliberada.

Testes

  • Vitest in-process (tests/contract/edge-functions/): all-contracts.test.ts parametrizado via import.meta.glob, valida examples.valid[] + examples.invalid[] (com expectedPath) + matriz negativa auto-derivada (missing/wrong/empty) por introspecção do ZodObject.
  • versioning.test.ts: resolução de versão, default v1, headers Deprecation/Sunset, UNSUPPORTED_VERSION, backwards-compat v1↔v2.
  • error-response.test.ts: shape único em todas as respostas, code required para campo ausente, dot-notation para paths (products.0.sku).
  • inventory.test.ts: gate de CI (cada Edge Function tem contrato OU allowlist; sem órfãos; sem conflito).
  • Deno colocados em product-webhook/contract_test.ts, webhook-inbound/contract_test.ts, webhook-dispatcher/contract_test.ts exercitando o _shared/zod-validate.ts no runtime Deno real.

Resultado: 4 arquivos de teste, 125 testes passando, ~2.5s.

Test plan

  • npm test -- tests/contract → 125 passed (4 files)
  • ESLint baseline gate → drift positivo (1 erro eliminado)
  • Frontend grep para shape antigo → nenhum consumidor da forma {error, details} ou status 400 de validação
  • Deno tests em CI: deno test --no-check --allow-env --allow-net=none supabase/functions/{product-webhook,webhook-inbound,webhook-dispatcher}/contract_test.ts (rodam no workflow ci.yml que já configura Deno 2.x)
  • Live runner manual contra staging: SUPABASE_URL=... CONTRACT_TEST_TOKEN=... npm run test:contract
  • Smoke do product-webhook v2 em staging com payload real do n8n

Docs

  • docs/RUNBOOKS/contracts-and-versioning.md — fluxo para criar v2, política de Sunset, allowlist, comandos
  • Entrada no CHANGELOG.md com BREAKING destacado

https://claude.ai/code/session_01FeMg7gMQAXtfxJDDVV3YVV


Generated by Claude Code


Summary by cubic

Camada compartilhada de contratos com zod para 18 Edge Functions, erro 422 padronizado e versionamento via X-Contract-Version (v1/v2 no product-webhook) para reduzir divergências e facilitar evolução sem quebras. Inclui gate de inventário no CI para impedir novas funções sem contrato.

  • New Features

    • Contratos centralizados com exemplos (valid/invalid) em _shared/contracts/, aplicados em 17 handlers.
    • Erro de validação único: 422 com { code, message, fields[] } (+ 400 para INVALID_JSON, MISSING_BODY, UNSUPPORTED_VERSION).
    • Versionamento por header X-Contract-Version com Deprecation e Sunset; product-webhook v1 deprecated (Sunset 2026-08-22), v2 estável com price: { amount, currency }.
    • Gate de inventário no CI: exige contrato ou allowlist explícita; suíte de testes cobre contracts, versionamento e shape de erro.
  • Migration

    • Breaking: respostas de validação mudam de 400 {error, details} para 422 { code, message, fields[] }.
    • product-webhook: clientes legados devem enviar X-Contract-Version: v1 até migrarem para v2; recomendado adotar price como objeto { amount, currency }.
    • Novas Edge Functions precisam de contrato ou entrada na allowlist; ver docs/RUNBOOKS/contracts-and-versioning.md.

Written for commit cb29762. Summary will update on new commits. Review in cubic

…2 para Edge Functions

Estabelece camada compartilhada _shared/contracts/ como fonte única de schemas,
exemplos válidos/inválidos e registry de versionamento para 18 Edge Functions
(3 webhooks externos + 15 com validação prévia). Padroniza todas as respostas
de validação para HTTP 422 com shape { code, message, fields[] }, com
mecanismo X-Contract-Version / Deprecation / Sunset exercitado em
product-webhook v1 (deprecated, sunset 2026-08-22) ↔ v2 (stable, price como
objeto {amount,currency}).

Camada nova:
  • _shared/contracts/error-response.ts — shape único + helpers 422/400
  • _shared/contracts/versioning.ts — resolveContractVersion + deprecation
  • _shared/contracts/<endpoint>.contracts.ts (×18) — registry + examples
  • _shared/zod-validate.ts evoluído — parseRequestWithContract + 422

17 handlers refatorados para usar parseBodyWithSchema/parseRequestWithContract
(lógica de negócio inalterada; schemas movidos para contracts/).

Testes:
  • tests/contract/edge-functions/all-contracts.test.ts — parametrizado via
    import.meta.glob, cobre examples + matriz negativa auto-derivada
  • error-response.test.ts, versioning.test.ts (v1↔v2 backwards-compat)
  • inventory.test.ts — gate de CI exigindo contrato ou allowlist explícita
    para toda Edge Function (61 funções na allowlist hoje, dívida explícita)
  • Deno colocados: product-webhook/webhook-inbound/webhook-dispatcher
    contract_test.ts cobrindo o fluxo Request→Response no runtime Deno

scripts/contract-testing.mjs reescrito para enumerar contratos via filesystem
e reusar examples (DRY contra os schemas).

Documentação: docs/RUNBOOKS/contracts-and-versioning.md + entrada no CHANGELOG
sinalizando BREAKING CHANGE (400→422 + shape novo). Frontend não consome a
forma antiga; verificado via grep.

Resultado: 125 testes de contrato passando (4 arquivos), ESLint baseline com
drift positivo (1 erro eliminado).

https://claude.ai/code/session_01FeMg7gMQAXtfxJDDVV3YVV
@vercel
Copy link
Copy Markdown

vercel Bot commented May 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
we-dream-big Ready Ready Preview, Comment May 22, 2026 3:09am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c01a513b-c55d-4d25-ae6c-8c9f4b490733

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/webhook-contract-tests-9lJDT

Comment @coderabbitai help to get the list of available commands and usage tips.

@supabase
Copy link
Copy Markdown

supabase Bot commented May 22, 2026

This pull request has been ignored for the connected project doufsxqlfjyuvxuezpln due to reaching the limit of concurrent preview branches.
Go to Project Integrations Settings ↗︎ if you wish to update this limit.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@adm01-debug
Copy link
Copy Markdown
Owner Author

Fechando como duplicata. PR #45 já entregou a infraestrutura equivalente (caminhos _shared/contracts/, envelope 422, v1/v2) e foi mergeado em main em 73b8a82. Próxima onda de migração para mais 13 endpoints está em #69.

@adm01-debug adm01-debug deleted the claude/webhook-contract-tests-9lJDT branch May 24, 2026 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants