chore(contracts): centralize Zod pinning via _shared/contracts barrel (closes #52)#343
chore(contracts): centralize Zod pinning via _shared/contracts barrel (closes #52)#343adm01-debug wants to merge 1 commit into
Conversation
…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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Updates to Preview Branch (chore/contracts-zod-pinning-via-barrel-52) ↗︎
Tasks are run on every commit but only new migration files are pushed.
❌ Branch Error • Mon, 25 May 2026 18:11:35 UTC View logs for this Workflow Run ↗︎. |
WalkthroughPR implementa centralização de Zod (validador de schemas) consolidando 21 imports diretos de URLs remotas para um barrel local ChangesCentralização de Zod com Gate de CI
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:
Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the Comment |
There was a problem hiding this comment.
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.mjsand wires it intonpm run check:zod-pinning. - Enforces the guardrail in CI (
qualityjob) 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', |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
scripts/check-zod-pinning.mjs (1)
21-33: ⚡ Quick winRegex do gate é sensível a quebra de linha (robustez do guardrail)
Hoje as ocorrências reais de
https://...zodestão apenas emsupabase/functions/_shared/contracts/e são capturadas pelogrepatual; não há casos fora desse root mesmo com busca multilinha. Ainda assim, o padrão lineargreppode deixar passar import/export quandofrome 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
📒 Files selected for processing (24)
.github/workflows/ci.ymlpackage.jsonscripts/check-zod-pinning.mjssupabase/functions/commemorative-dates/index.tssupabase/functions/comparison-ai-advisor/index.tssupabase/functions/connection-tester/index.tssupabase/functions/crm-db-bridge/index.tssupabase/functions/dropbox-list/index.tssupabase/functions/elevenlabs-tts/index.tssupabase/functions/external-db-bridge/index.tssupabase/functions/external-db-inspect/index.tssupabase/functions/full-op-diagnostics/index.tssupabase/functions/generate-ad-image/index.test.tssupabase/functions/generate-ad-image/index.tssupabase/functions/magic-up-score/index.tssupabase/functions/mcp-keys-issue/index.tssupabase/functions/mcp-keys-revoke/index.tssupabase/functions/mcp-keys-rotate/index.tssupabase/functions/mcp-keys-update/index.tssupabase/functions/quote-sync/index.tssupabase/functions/rate-limit-check/index.tssupabase/functions/secrets-manager/index.tssupabase/functions/verify-email/index.tssupabase/functions/voice-agent/index.ts
There was a problem hiding this comment.
💡 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', |
There was a problem hiding this comment.
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', |
There was a problem hiding this comment.
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', |
There was a problem hiding this comment.
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 👍 / 👎.
Contexto
Fecha #52 — última peça da saga "contracts" iniciada no #45.
Desde o #45, o pacote
supabase/functions/_shared/contracts/já re-exportazdo 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:esm.sh/zod@3.23.8deno.land/x/zod@v3.23.8/mod.tsdeno.land/x/zod@v3.22.4/mod.tsO que muda
21 imports migrados
Todos viraram:
Guardrail anti-regressão
scripts/check-zod-pinning.mjs— script queexit 1se achar import direto de Zod fora de_shared/contracts/. Integrado ao CI:Roda no job
qualitydo.github/workflows/ci.ymllogo após o ESLint baseline gate.Validação
;, com@versionou/mod.ts)_shared/contracts/_shared/contracts/schemas/*.ts) continuam puxando do esm.sh — eles são o ponto de centralizaçãoBenefícios
Diff stat
supabase/functions/<name>/index.ts— 1 linha cada (import substituído)scripts/check-zod-pinning.mjspackage.json,.github/workflows/ci.ymlTotal: 24 arquivos, +71/−25
Summary by cubic
Centralizes
zodusage by importingzfromsupabase/functions/_shared/contractseverywhere and adds a CI gate to block directzodimports. This shrinks Edge Function bundles and ensures a singlezod@3.23.8, making future upgrades easier.zodimports withimport { z } from "../_shared/contracts/index.ts".scripts/check-zod-pinning.mjsandnpm run check:zod-pinning; wired into.github/workflows/ci.ymlafter the ESLint baseline gate.https://esm.sh/zod@3.23.8inside_shared/contractsschemas.Written for commit 7a49fb9. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
Release Notes