Skip to content

chore(contracts): centralize Zod pinning via _shared/contracts barrel (closes #52)#343

Closed
adm01-debug wants to merge 1 commit into
mainfrom
chore/contracts-zod-pinning-via-barrel-52
Closed

chore(contracts): centralize Zod pinning via _shared/contracts barrel (closes #52)#343
adm01-debug wants to merge 1 commit into
mainfrom
chore/contracts-zod-pinning-via-barrel-52

Conversation

@adm01-debug
Copy link
Copy Markdown
Owner

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

Contexto

Fecha #52 — última peça da saga "contracts" iniciada no #45.

Desde o #45, o pacote supabase/functions/_shared/contracts/ já re-exporta z do pin canônico (https://esm.sh/zod@3.23.8). Mas 21 Edge Functions ainda importavam Zod diretamente, com mix de 4 versões diferentes:

Pinning antigo Funções
esm.sh/zod@3.23.8 commemorative-dates, crm-db-bridge, dropbox-list, external-db-inspect, full-op-diagnostics, mcp-keys-issue, mcp-keys-revoke, mcp-keys-rotate, mcp-keys-update, quote-sync
deno.land/x/zod@v3.23.8/mod.ts connection-tester, external-db-bridge, generate-ad-image (×2), magic-up-score, rate-limit-check, secrets-manager, verify-email
deno.land/x/zod@v3.22.4/mod.ts comparison-ai-advisor, elevenlabs-tts, voice-agent

O que muda

21 imports migrados

Todos viraram:

import { z } from "../_shared/contracts/index.ts";

Guardrail anti-regressão

scripts/check-zod-pinning.mjs — script que exit 1 se achar import direto de Zod fora de _shared/contracts/. Integrado ao CI:

- name: Zod pinning gate (issue #52 — barrel centralization)
  run: npm run check:zod-pinning

Roda no job quality do .github/workflows/ci.yml logo após o ESLint baseline gate.

Validação

$ node scripts/check-zod-pinning.mjs
✓ Pinning de Zod centralizado (0 imports diretos fora de _shared/contracts/)
  • 21/21 imports substituídos via script Node determinístico (regex testado em todos os formatos: aspas duplas/simples, com/sem ;, com @version ou /mod.ts)
  • 0 imports diretos restantes fora de _shared/contracts/
  • Schemas internos (_shared/contracts/schemas/*.ts) continuam puxando do esm.sh — eles são o ponto de centralização

Benefícios

  1. Bundle size das Edge Functions diminui — 4 versões de Zod coexistiam, agora só 1
  2. Comportamento previsível — mesma versão garante mesmas semânticas em todos os endpoints
  3. Migração futura para Zod 4 vira PR único no barrel, não 21 PRs separados
  4. Anti-regressão automatizada — CI bloqueia qualquer import direto novo

Diff stat

  • 21 arquivos supabase/functions/<name>/index.ts — 1 linha cada (import substituído)
  • 1 arquivo novo: scripts/check-zod-pinning.mjs
  • 2 arquivos de infra atualizados: package.json, .github/workflows/ci.yml

Total: 24 arquivos, +71/−25


Summary by cubic

Centralizes zod usage by importing z from supabase/functions/_shared/contracts everywhere and adds a CI gate to block direct zod imports. This shrinks Edge Function bundles and ensures a single zod@3.23.8, making future upgrades easier.

  • Refactors
    • Replaced 21 direct zod imports with import { z } from "../_shared/contracts/index.ts".
    • Added scripts/check-zod-pinning.mjs and npm run check:zod-pinning; wired into .github/workflows/ci.yml after the ESLint baseline gate.
    • Central pin stays at https://esm.sh/zod@3.23.8 inside _shared/contracts schemas.

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

Summary by CodeRabbit

Release Notes

  • Chores
    • Implementada centralização do validador de esquema em módulo compartilhado para garantir consistência em toda a plataforma
    • Adicionada verificação automática de integridade na pipeline de integração contínua para validar conformidade da arquitetura

Review Change Stack

…closes #52)

Substitui 21 imports diretos de Zod (mix de esm.sh@3.22.4, esm.sh@3.23.8,
deno.land/x@3.22.4 e deno.land/x@3.23.8) pelo barrel canônico:

    import { z } from "../_shared/contracts/index.ts";

O barrel já re-exportava `z` do pin canônico `https://esm.sh/zod@3.23.8`
desde o #45. Este PR fecha o ciclo migrando os 21 call sites restantes
e adiciona guardrail anti-regressão.

## Mudanças

- 21 arquivos `supabase/functions/<name>/index.ts` migrados (1 import cada)
- `scripts/check-zod-pinning.mjs` — script que falha com exit 1 se achar
  qualquer import direto de zod fora de `_shared/contracts/`
- `package.json` — novo script `check:zod-pinning`
- `.github/workflows/ci.yml` — step "Zod pinning gate" adicionado ao
  pipeline (roda após o ESLint baseline gate)

## Benefícios

- Bundle size das Edge Functions diminui (Zod 3.23 single-version vs
  4 versões diferentes coexistindo)
- Migração futura para Zod 4 vira PR único no barrel, não 21 PRs
- Comportamento previsível (mesma versão = mesmas semânticas)

## Validação

- `node scripts/check-zod-pinning.mjs` → "✓ Pinning de Zod centralizado"
- `grep -rn 'from.*zod' supabase/functions/ | grep -v _shared/contracts/`
  → 0 hits
- Schemas internos (`_shared/contracts/schemas/*.ts`) continuam
  importando direto do esm.sh — esse é o ponto de centralização

## Sobre #48 (referenciado como dependência neste issue)

Auditoria pós-fato: as 3 funções P2 (`force-global-logout`, `e2e-cleanup`,
`block-ip-temporarily`) já usam `parseContract` com schemas v1+v2. Será
fechado em paralelo com nota documental.

Refs: closes #52
Copilot AI review requested due to automatic review settings May 25, 2026 18:05
@vercel
Copy link
Copy Markdown

vercel Bot commented May 25, 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 25, 2026 6:08pm

@supabase
Copy link
Copy Markdown

supabase Bot commented May 25, 2026

Updates to Preview Branch (chore/contracts-zod-pinning-via-barrel-52) ↗︎

Deployments Status Updated
Database Mon, 25 May 2026 18:08:02 UTC
Services Mon, 25 May 2026 18:08:02 UTC
APIs Mon, 25 May 2026 18:08:02 UTC

Tasks are run on every commit but only new migration files are pushed.
Close and reopen this PR if you want to apply changes from existing seed or migration files.

Tasks Status Updated
Configurations Mon, 25 May 2026 18:08:09 UTC
Migrations Mon, 25 May 2026 18:11:35 UTC
Seeding ⏸️ Mon, 25 May 2026 18:07:54 UTC
Edge Functions ⏸️ Mon, 25 May 2026 18:07:54 UTC

❌ Branch Error • Mon, 25 May 2026 18:11:35 UTC

ERROR: cannot change return type of existing function (SQLSTATE 42P13)
At statement: 10
CREATE OR REPLACE FUNCTION public.fn_run_and_persist_smoke_tests()
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path TO 'public'
AS $function$
DECLARE
  v_ran_at timestamptz := now();
BEGIN
  IF NOT public.is_admin_or_above((SELECT auth.uid())) THEN
    RAISE EXCEPTION 'not authorized';
  END IF;

  INSERT INTO public.smoke_test_runs (
    ran_at,
    test_name,
    test_category,
    result,
    details,
    duration_ms
  )
  SELECT
    v_ran_at,
    test_name,
    test_category,
    result,
    details,
    duration_ms
  FROM public.fn_run_smoke_tests();
END;
$function$

View logs for this Workflow Run ↗︎.
Learn more about Supabase for Git ↗︎.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

Walkthrough

PR implementa centralização de Zod (validador de schemas) consolidando 21 imports diretos de URLs remotas para um barrel local _shared/contracts. Adiciona script Node/ESM check-zod-pinning.mjs que varre funções Supabase por imports diretos de Zod e falha em CI se violações forem encontradas, impedindo regressões.

Changes

Centralização de Zod com Gate de CI

Layer / File(s) Summary
CI Guardrail e Script de Validação
.github/workflows/ci.yml, package.json, scripts/check-zod-pinning.mjs
Novo step Zod pinning gate no job quality executa script Node que usa grep para escanear supabase/functions/ por imports diretos de Zod via URL (padrão https://, deno.land, esm.sh), filtra matches dentro do diretório permitido _shared/contracts/, imprime violações detalhadas e context link em caso de falha (exit code 1).
Migrações de 21 Endpoints
supabase/functions/commemorative-dates/*, supabase/functions/comparison-ai-advisor/*, supabase/functions/connection-tester/*, supabase/functions/crm-db-bridge/*, supabase/functions/dropbox-list/*, supabase/functions/elevenlabs-tts/*, supabase/functions/external-db-bridge/*, supabase/functions/external-db-inspect/*, supabase/functions/full-op-diagnostics/*, supabase/functions/generate-ad-image/*, supabase/functions/magic-up-score/*, supabase/functions/mcp-keys-issue/*, supabase/functions/mcp-keys-revoke/*, supabase/functions/mcp-keys-rotate/*, supabase/functions/mcp-keys-update/*, supabase/functions/quote-sync/*, supabase/functions/rate-limit-check/*, supabase/functions/secrets-manager/*, supabase/functions/verify-email/*, supabase/functions/voice-agent/*
Todos os 21 endpoints trocam import de z (Zod) de URLs remotas (deno.land/x/zod@v3.23.8, esm.sh/zod@3.23.8) para reexportação centralizada em ../_shared/contracts/index.ts. Mudança é puramente de origem do módulo; schemas de validação (BodySchema, ActionSchema), fluxos de autenticação, handlers, testes e tratamento de erros permanecem sem alterações funcionais.

Sequence Diagram(s)

Condições não atendidas para gerar diagrama: mudanças são apenas de reconfiguração de imports sem introdução de novo fluxo de componentes ou alteração significativa de controle de fluxo.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Justificativa: PR implementa mudança homogênea e repetitiva (mesmo padrão de import em 21 arquivos) com script de validação direto. Verificar:

  • Script check-zod-pinning.mjs usa execSync + grep com tratamento correto de saída (exit codes e stderr)
  • CI step está posicionado corretamente (após type check, antes de outros checks)
  • Padrão de import é consistente em todos os endpoints
  • Nenhuma mudança em lógica de validação ou fluxo de negócio

Possibly related issues

Possibly related PRs

  • adm01-debug/promo-gifts-v4#155: Implementa a infraestrutura complementar (_shared/contracts barrel com _zod.ts pinning) que este PR depende para funcionar; este PR força o uso dessa centralização via CI guardrail.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed O título descreve com precisão a mudança principal: centralização de pinning do Zod através do barrel _shared/contracts, com referência ao issue #52.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/contracts-zod-pinning-via-barrel-52

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Centralizes Zod pinning for Supabase Edge Functions by switching function-level Zod imports to the _shared/contracts barrel and adding a CI guard to prevent regressions (issue #52).

Changes:

  • Migrates Zod imports in 21 Edge Functions (plus one Deno test) to ../_shared/contracts/index.ts.
  • Adds scripts/check-zod-pinning.mjs and wires it into npm run check:zod-pinning.
  • Enforces the guardrail in CI (quality job) to block new direct Zod imports.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
supabase/functions/voice-agent/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/verify-email/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/secrets-manager/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/rate-limit-check/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/quote-sync/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/mcp-keys-update/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/mcp-keys-rotate/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/mcp-keys-revoke/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/mcp-keys-issue/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/magic-up-score/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/generate-ad-image/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/generate-ad-image/index.test.ts Switches Zod import to _shared/contracts barrel for the mirrored schema.
supabase/functions/full-op-diagnostics/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/external-db-inspect/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/external-db-bridge/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/elevenlabs-tts/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/dropbox-list/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/crm-db-bridge/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/connection-tester/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/comparison-ai-advisor/index.ts Switches Zod import to _shared/contracts barrel.
supabase/functions/commemorative-dates/index.ts Switches Zod import to _shared/contracts barrel.
scripts/check-zod-pinning.mjs Adds a repo guard script intended to detect direct Zod imports outside _shared/contracts.
package.json Adds check:zod-pinning script entry.
.github/workflows/ci.yml Runs the Zod pinning gate in the quality job.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

let output = '';
try {
output = execSync(
'grep -rn "from[[:space:]]*[\\"\\\\\']https://.*zod" supabase/functions/ 2>/dev/null || true',
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/check-zod-pinning.mjs (1)

21-33: ⚡ Quick win

Regex do gate é sensível a quebra de linha (robustez do guardrail)

Hoje as ocorrências reais de https://...zod estão apenas em supabase/functions/_shared/contracts/ e são capturadas pelo grep atual; não há casos fora desse root mesmo com busca multilinha. Ainda assim, o padrão linear grep pode deixar passar import/export quando from e a URL ficarem em linhas diferentes, então vale endurecer a detecção (scanner em Node ou regex multilinha) para não enfraquecer o anti-regressão no futuro.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-zod-pinning.mjs` around lines 21 - 33, The current grep-based
check (invoked via execSync and assigned to output) can miss imports where the
token "from" and the "https://...zod" URL are on separate lines; replace the
fragile linear grep with a Node-side scanner that recursively reads files under
supabase/functions, then run a multiline regex (e.g.,
/from[\s\S]*?["'`]https:\/\/.*zod["'`]/mi) against each file's content to detect
imports/exports spanning lines, filter out ALLOWED_ROOT matches, and set
violations accordingly (updating the logic that computes output/violations
instead of relying on the single-line grep).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@scripts/check-zod-pinning.mjs`:
- Around line 21-33: The current grep-based check (invoked via execSync and
assigned to output) can miss imports where the token "from" and the
"https://...zod" URL are on separate lines; replace the fragile linear grep with
a Node-side scanner that recursively reads files under supabase/functions, then
run a multiline regex (e.g., /from[\s\S]*?["'`]https:\/\/.*zod["'`]/mi) against
each file's content to detect imports/exports spanning lines, filter out
ALLOWED_ROOT matches, and set violations accordingly (updating the logic that
computes output/violations instead of relying on the single-line grep).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bc6bf3ee-2788-47bc-8e95-b9807c2316c3

📥 Commits

Reviewing files that changed from the base of the PR and between d64e1bd and 7a49fb9.

📒 Files selected for processing (24)
  • .github/workflows/ci.yml
  • package.json
  • scripts/check-zod-pinning.mjs
  • supabase/functions/commemorative-dates/index.ts
  • supabase/functions/comparison-ai-advisor/index.ts
  • supabase/functions/connection-tester/index.ts
  • supabase/functions/crm-db-bridge/index.ts
  • supabase/functions/dropbox-list/index.ts
  • supabase/functions/elevenlabs-tts/index.ts
  • supabase/functions/external-db-bridge/index.ts
  • supabase/functions/external-db-inspect/index.ts
  • supabase/functions/full-op-diagnostics/index.ts
  • supabase/functions/generate-ad-image/index.test.ts
  • supabase/functions/generate-ad-image/index.ts
  • supabase/functions/magic-up-score/index.ts
  • supabase/functions/mcp-keys-issue/index.ts
  • supabase/functions/mcp-keys-revoke/index.ts
  • supabase/functions/mcp-keys-rotate/index.ts
  • supabase/functions/mcp-keys-update/index.ts
  • supabase/functions/quote-sync/index.ts
  • supabase/functions/rate-limit-check/index.ts
  • supabase/functions/secrets-manager/index.ts
  • supabase/functions/verify-email/index.ts
  • supabase/functions/voice-agent/index.ts

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a49fb958b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

let output = '';
try {
output = execSync(
'grep -rn "from[[:space:]]*[\\"\\\\\']https://.*zod" supabase/functions/ 2>/dev/null || true',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detect all direct Zod specifiers in pinning gate

The new guard only searches for from ... "https://.*zod", so it misses other direct Zod imports (for example npm:zod) outside _shared/contracts, even though the script header says it should fail on any direct import outside that folder. In this repo, direct npm:zod imports already exist (e.g. supabase/functions/expert-chat/index.ts), so the gate can report a clean state while centralization is still bypassed and future regressions of the same form will not be blocked.

Useful? React with 👍 / 👎.

let output = '';
try {
output = execSync(
'grep -rn "from[[:space:]]*[\\"\\\\\']https://.*zod" supabase/functions/ 2>/dev/null || true',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match multiline import specifiers in pinning gate

The regex is line-oriented and only matches when from and the URL are on the same line, so a direct import split across lines (e.g. import { z } from followed by the URL on the next line) is not detected and the script exits successfully. That allows straightforward bypasses of the CI guard while still importing Zod directly outside _shared/contracts.

Useful? React with 👍 / 👎.

let output = '';
try {
output = execSync(
'grep -rn "from[[:space:]]*[\\"\\\\\']https://.*zod" supabase/functions/ 2>/dev/null || true',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Propagate grep failures instead of forcing success

The command appends || true and suppresses stderr, which converts grep execution errors into a passing check. If the scan path is wrong, files are unreadable, or grep fails for any runtime reason, this gate still prints success and returns 0, so CI can silently skip enforcement instead of failing closed.

Useful? React with 👍 / 👎.

@adm01-debug adm01-debug deleted the chore/contracts-zod-pinning-via-barrel-52 branch May 25, 2026 18:18
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.

3 participants