Por que você não deve conectar um protótipo feito no v0 diretamente ao banco de dados da empresa e como fazer essa conexão de forma segura
Um funcionário não desenvolvedor cria um aplicativo web incrível em três dias usando ferramentas de "vibe coding" como v0 ou Cursor. O CEO fica empolgado e sugere imediatamente conectá-lo ao banco de dados de produção para que os clientes possam usá-lo. É nesse momento que a equipe de desenvolvimento ou o CTO começam a suar frio. Ao abrir o código gerado por IA, eles se deparam com a string de conexão do banco de dados (DSN) inserida diretamente no meio de um componente cliente, ou consultas SQL sendo executadas sem qualquer tipo de validação.
Subir isso diretamente para o servidor de produção é pedir para ter problemas. O relatório OWASP Top 10 for LLM Applications 2025 destaca a concessão excessiva de permissões em códigos gerados por IA (LLM06) e a falta de validação de entradas (LLM05) como os riscos de segurança mais perigosos. Na realidade, 73% das violações de segurança em aplicações web exploram a ausência de validação de dados de entrada.
Para proteger o banco de dados da empresa sem podar a produtividade dos não desenvolvedores, é necessário colocar uma camada sólida de controle entre o protótipo e o banco de dados.
Camada de validação com Zod para cortar o acesso direto do cliente ao banco de dados
A primeira coisa a fazer é bloquear o caminho para que o aplicativo criado pelo não desenvolvedor não chame o banco de dados diretamente. Coloque um Server Route Handler do Next.js App Router como proxy e valide em tempo real os dados que chegam usando a biblioteca Zod. A checagem de tipos do TypeScript funciona apenas durante o desenvolvimento e não impede que o servidor caia quando um usuário real envia dados malformatados.
| Item de validação |
Validação na UI do navegador |
Camada Proxy Zod no Server-Side |
| Local de execução |
Navegador do cliente |
Runtime serverless da Vercel |
| Segurança |
Facilmente burlada pelas ferramentas de desenvolvedor |
Bloqueio forçado no servidor para proteger o banco de dados |
| Validação de dados |
Checagem superficial de texto |
Validação precisa de tipos e limites de valores em tempo de execução |
| Tratamento de falhas |
Exibe mensagem de aviso na tela |
Retorna HTTP 400 e registra o erro no Sentry |
O processo de construção é simples:
- Comece criando o arquivo
app/api/v1/customer-records/route.ts no projeto.
- Defina o schema Zod. Configure as regras para que
companyName tenha pelo menos 2 caracteres, contactEmail siga o formato de e-mail e employeeCount aceite apenas inteiros positivos.
- Inspecione a requisição recebida via
request.json() usando schema.parse(). Apenas os dados validados são inseridos no banco de dados através do Prisma ORM; se a validação falhar, um erro 400 é retornado imediatamente.
Além da validação no nível da aplicação, você também deve erguer defesas no próprio banco de dados. Se estiver usando o Supabase baseado em PostgreSQL, a configuração de Row Level Security (RLS) é a solução. Guarde as informações de função do usuário em raw_app_meta_data, que é manipulado apenas por administradores, em vez de raw_user_meta_data, que pode ser alterado pelo usuário, e valide o JWT.
`sql
-- 1. Habilitar RLS na tabela
ALTER TABLE public.enterprise_documents ENABLE ROW LEVEL SECURITY;
-- 2. Criar função para extrair a função do usuário a partir do JWT
CREATE OR REPLACE FUNCTION get_user_role()
RETURNS text AS
SELECTNULLIF(currentsetting(′request.jwt.claims′,true)::json−>′appmetadata′−>>′userrole′,′′); LANGUAGE sql STABLE;
-- 3. Política que permite a leitura apenas se for do mesmo departamento ou se for administrador
CREATE POLICY "Department Access Policy" ON public.enterprise_documents
FOR SELECT USING (
get_user_role() = 'admin' OR
department = (current_setting('request.jwt.claims', true)::json->'app_metadata'->>'department')
);
`
Com isso configurado, mesmo que um não desenvolvedor vaze acidentalmente a chave de serviço (Service Role Key) no código, os documentos confidenciais de outros departamentos nunca serão expostos.
Prevenindo o vazamento de chaves de API com varredura de código-fonte
Como as ferramentas de IA são projetadas para focar primeiro em colocar a interface no ar, elas frequentemente usam chaves de API ou strings de conexão de banco de dados em locais expostos ao navegador. O erro mais comum é adicionar o prefixo NEXT_PUBLIC_ em qualquer lugar. No Next.js, variáveis com esse prefixo são incluídas como texto puro nos arquivos JavaScript do navegador. No momento em que você cria uma variável como NEXT_PUBLIC_OPENAI_API_KEY, qualquer pessoa que saiba abrir as ferramentas de desenvolvedor (F12) pode pegar sua chave de API e usá-la livremente.
Basta olhar para o incidente de segurança ocorrido na infraestrutura da Vercel em abril de 2026. Quando as permissões de uma ferramenta de IA de terceiros integrada foram comprometidas, variáveis de ambiente não ocultas foram expostas, forçando inúmeras equipes a passar a noite reemitindo senhas de banco de dados e chaves de API uma a uma.
É impossível para os humanos inspecionarem manualmente cada um desses erros. Você deve integrar a ferramenta de análise estática Gitleaks ao GitHub Actions para remover esses riscos automaticamente antes de fazer o merge do código.
`yaml
name: Security Scan
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
gitleaks-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install and Run Gitleaks
run: |
wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.0/gitleaks_8.18.0_linux_x64.tar.gz
tar -xzvf gitleaks_8.18.0_linux_x64.tar.gz
sudo mv gitleaks /usr/local/bin/
gitleaks detect --source=. --verbose --redact --exit-code=1
public-env-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check Unsafe Public Keys
run: |
UNSAFE=(grep -rn "NEXT_PUBLIC_.*\(SECRET\|KEY\|PASSWORD\|TOKEN\|DSN\)" . || true)
if [ -n "UNSAFE" ]; then
echo "클라이언트에 노출된 민감 변수 발견:"
echo "$UNSAFE"
exit 1
fi
`
Ao configurar essa pipeline, se um não desenvolvedor tentar fazer um push contendo uma chave de API no código-fonte ou em uma variável NEXT_PUBLIC_, o deploy será bloqueado automaticamente.
Ao registrar variáveis no painel da Vercel, certifique-se de separar claramente os escopos de Development, Preview e Production. Em particular, ative sempre a caixa de seleção "Sensitive Environment Variable". Isso garante que os dados sejam criptografados, impedindo que apareçam nos logs de build ou sejam copiados como texto simples no painel.
Como não desenvolvedores podem se recuperar de uma falha em apenas 30 segundos
Se os servidores da OpenAI ou Anthropic ficarem fora do ar ou apresentarem lentidão, todo o handler serverless entrará em estado de espera, desencadeando falhas em cascata. Nesses casos, você deve implementar um Circuit Breaker usando a biblioteca opossum do Node.js.
`typescript
import CircuitBreaker from 'opossum';
async function callLLM(prompt: string) {
// Lógica de chamada da API do LLM
}
const options = {
timeout: 5000, // Considera falha se passar de 5 segundos
errorThresholdPercentage: 50, // Abre o circuito se a taxa de falhas ultrapassar 50%
resetTimeout: 30000 // Tenta novamente após 30 segundos
};
const breaker = new CircuitBreaker(callLLM, options);
breaker.fallback(() => ({ error: "A resposta da IA está atrasada. Por favor, tente novamente em breve." }));
`
Se a resposta da API demorar, uma mensagem orientativa pré-configurada é enviada em apenas 0,1 segundo, evitando que todo o serviço caia.
Também conectamos webhooks do Sentry e do Slack para que criadores não desenvolvedores fiquem cientes de situações de falha imediatamente.
`typescript
// app/api/webhooks/sentry-to-slack/route.ts
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
try {
const event = await request.json();
const webhookUrl = process.env.SLACK_INCOMING_WEBHOOK_URL;
if (!webhookUrl) return NextResponse.json({ error: 'Webhook ausente' }, { status: 500 });
const title = event.data?.issue?.title || 'Erro desconhecido no sistema';
const issueUrl = event.data?.issue?.permalink || '#';
await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
blocks: [
{
type: 'header',
text: { type: 'plain_text', text: '🚨 Erro em Produção Detectado' }
},
{
type: 'section',
text: { type: 'mrkdwn', text: `*Detalhes do erro:*
${title}` }
},
{
type: 'actions',
elements: [
{
type: 'button',
text: { type: 'plain_text', text: 'Ver relatório no Sentry' },
url: issueUrl,
style: 'danger'
}
]
}
]
})
});
return NextResponse.json({ success: true });
} catch (err) {
return NextResponse.json({ error: 'Falha no Webhook' }, { status: 500 });
}
}
`
Se um erro de nível P1 fizer a página principal cair, não há necessidade de esperar por um desenvolvedor. A Vercel mantém os deploys anteriores intactos, permitindo reverter para o estado anterior com apenas alguns cliques:
- Receba o alerta de falha P1 no canal do Slack.
- Vá para a aba "Deployments" no painel da Vercel.
- Encontre na lista o último deploy que estava funcionando corretamente (status "Ready").
- Clique no botão de três pontos (...) no lado direito e selecione "Promote to Production".
Aguarde 30 segundos e o roteamento do domínio mudará para a versão anterior. Com validação Zod, varredura do Gitleaks e procedimentos de rollback na Vercel configurados, você pode deixar os não desenvolvedores criarem aplicativos à vontade e ainda assim ter uma noite de sono tranquila.