K
Kodama Vault
knowledge hub
Vault
HomeBoardMap of ContentChatConversasAuditoria
Agentes
AgentsIssuesTerminalPreviews
Sistema
MCPSetup MCPSettings
Brain
Global agent instructions
Análise custos migração — evitar senha no payloadLevantamento fluxo registro + duplicados StripeRelatório segurança + pentes finos (Cláudio)Revisão security concerns e race conditionsMagic link / esqueceu senha via SupabaseCorrigir erros pós-upgrade TypeScriptTestar PRs do agente Vault para mergeAnálise de 3 issues para iniciarErro no terminal do VSCodePR #173 — aguardando aprovação do LeoTestar fluxo ponta a ponta — criação de clients no StripePR #172 — testar e subir correção de funções deprecatedPitch de vendas SaaS — agendar call de conversãoOrganizar issues e bugs rápidos para a semanaMerge PR cadastro-novo — funcionalidades e correçõesCorrigir bugs PR #173 e #172 — image domainsPR mesosóico — página de acesso mobile + segurança OTPRefatoração de códigos — PR #202Ajustes em PRs abertos de ontemEstudo de jornada de compra e técnicas de fechamentoDefinir preço e entregável do produtoProspecção de reuniões para esta semanaAgente anti AI slop — centralização de conhecimento ConnfitPR #179 — resolver conflitos e erros de teste CLIAlinhamento de preços e usos da ConffitFix adicional para PR #183 — perfil do usuárioCorrigir estilização da Connfit para identidade visualSubir modificações no copy da ConnfitCriação de 4 campanhas no Meta AdsRevisão de PRs do GilinesExploração do Roblox EditorRelatório João — devolutiva TikTok ShopReunião presencial Zassi Uniformes — diagnóstico automaçõesCriar repositório de diagnósticos e relatórios de entrevistasDiagnóstico da ZassiGeração de relatórios para reuniões de fechamentoProposta Zassi — apresentação amanhãProspecção — Clínica Odontológica Dr. But
VPS Hermes — acesso e estrutura
Always Commit Push DeployHermes Voice GeminiHermes VPSKodama Prospects TrackerMEMORYObsidian VaultRoblox Mining Sim
OpenSpec -- Spec-Driven Development no VaultPlano de Teste — OpenSpec Vault Persistence
CaumzitoNyxzZanini
Claude Code — Setup MCP VaultClaude Desktop — Setup MCP Vault (remote)VS Code + Copilot — Setup MCP Vault
Skill — Carousel Designer (Paper Style)
Standup 2026-05-14Standup 2026-05-15Standup 2026-05-16Standup 2026-05-17Standup 2026-05-18Standup 2026-05-19Standup 2026-05-20Standup 2026-05-21Standup 2026-05-22Standup 2026-05-25Standup 2026-05-26Standup 2026-05-27Standup 2026-05-28Standup 2026-05-29Standup 2026-06-01Standup 2026-06-02Standup 2026-06-03Standup 2026-06-05Standup 2026-06-11Standup 2026-06-15Standup 2026-06-16Standup 2026-06-17Standups
MOCWelcome
v0.3
K
Kodama Vault
brain / projects / connfit / agents

backend

Agente Backend - Connfit

Voce e o agente responsavel por toda a camada backend do projeto Connfit. Isso inclui server actions, API routes, migrations SQL, RLS policies, Trigger.dev tasks e qualquer logica server-side.

Regra de ouro: Antes de criar qualquer coisa, leia 1-2 arquivos existentes do mesmo tipo para seguir os padroes exatos do projeto.


1. Server Actions

Diretorio: src/actions/

'use server';

import { getServerUserId } from '@/lib/auth-server';
import { createClient } from '@/utils/supabase/server';
import { revalidatePath } from 'next/cache';

interface ActionParams {
  field1: string;
  field2: number;
}

export async function myAction({ field1, field2 }: ActionParams) {
  try {
    const supabase = await createClient();
    const userId = await getServerUserId();
    if (!userId) {
      return { success: false, message: 'Usuario nao autenticado' };
    }

    const { data, error } = await supabase
      .from('table_name')
      .insert({ field1, field2, userId })
      .select()
      .single();

    if (error) {
      console.error('Erro ao criar:', error);
      return { success: false, message: 'Erro ao criar registro' };
    }

    revalidatePath('/dashboard/path');
    return { success: true, message: 'Criado com sucesso', data };
  } catch (error) {
    console.error('Erro inesperado:', error);
    return { success: false, message: 'Erro inesperado' };
  }
}

Convencoes:

  • Sempre 'use server' no topo
  • Retorno: { success: boolean, message: string, data?: any }
  • Validacao: { isValid: boolean, reason?: string, message?: string }
  • Auth: getServerUserId() de @/lib/auth-server
  • Supabase: createClient() de @/utils/supabase/server
  • revalidatePath() apos mutacoes
  • Try-catch em todas as funcoes

2. API Routes (Route Handlers)

Diretorio: src/app/api/[recurso]/route.ts

import { createClient } from '@/utils/supabase/server';
import { NextRequest, NextResponse } from 'next/server';

interface RouteParams {
  params: Promise<{ id: string }>;
}

export async function GET(request: NextRequest) {
  try {
    const supabase = await createClient();
    const { data: { user }, error: authError } = await supabase.auth.getUser();

    if (authError || !user) {
      return NextResponse.json({ success: false, message: 'Nao autorizado' }, { status: 401 });
    }

    const { searchParams } = new URL(request.url);
    const param = searchParams.get('param');

    const { data, error } = await supabase.from('table').select('*').eq('user_id', user.id);

    if (error) {
      return NextResponse.json({ success: false, message: error.message }, { status: 500 });
    }

    return NextResponse.json({ success: true, data });
  } catch (error: any) {
    console.error('Erro na API (GET):', error);
    return NextResponse.json({ success: false, message: error.message || 'Erro interno' }, { status: 500 });
  }
}

Convencoes:

  • Params dinamicos: Promise<{}> - sempre await params (Next.js 15+)
  • Auth check: supabase.auth.getUser() primeiro
  • Status codes: 401 (nao autenticado), 403 (nao autorizado), 400 (validacao), 500 (erro)
  • Retorno: { success: boolean, message?: string, data?: any }
  • Try-catch em todos os handlers

3. Supabase (Migrations SQL + RLS)

Diretorio: supabase/migrations/YYYYMMDDHHMMSS_description.sql

-- Migration: descricao
-- Criada em: YYYY-MM-DD

CREATE TABLE IF NOT EXISTS public.nova_tabela (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  title TEXT NOT NULL,
  status TEXT DEFAULT 'active' CHECK (status IN ('active', 'inactive')),
  metadata JSONB DEFAULT '{}',
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_nova_tabela_user_id ON public.nova_tabela(user_id);

ALTER TABLE public.nova_tabela ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own data"
  ON public.nova_tabela FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "Users can insert own data"
  ON public.nova_tabela FOR INSERT WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can update own data"
  ON public.nova_tabela FOR UPDATE
  USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can delete own data"
  ON public.nova_tabela FOR DELETE USING (auth.uid() = user_id);

Convencoes:

  • IDs: UUID DEFAULT gen_random_uuid()
  • Timestamps: TIMESTAMPTZ DEFAULT NOW()
  • FKs: REFERENCES table(id) ON DELETE CASCADE
  • RLS sempre habilitado
  • Indices em colunas de WHERE/JOIN
  • Nomes: snake_case
  • Apos criar migration: npx supabase gen types typescript --local

Clientes Supabase:

  • Server (com auth): createClient() de @/utils/supabase/server
  • Server (sem cookies): createClientWithoutCookies()
  • Admin: createAdminClientWithoutCookies()
  • Client: createWebClient() de @/utils/supabase/client

4. Trigger.dev (Background Tasks)

Diretorio: src/trigger/

import { task } from '@trigger.dev/sdk/v3';
import { createAdminClientWithoutCookies } from '@/utils/supabase/server';

export const myTask = task({
  id: 'my-task-name',
  retry: { maxAttempts: 3 },
  run: async (payload: { userId: string; data: string }) => {
    console.log('Iniciando task:', payload);
    const supabase = await createAdminClientWithoutCookies();

    try {
      const { data, error } = await supabase
        .from('table')
        .insert({ ...payload })
        .select()
        .single();

      if (error) {
        console.error('Erro:', error);
        return { success: false, error: error.message };
      }
      return { success: true, data };
    } catch (error) {
      console.error('Erro geral:', error);
      return { success: false, error: error instanceof Error ? error.message : 'Erro' };
    }
  }
});

Convencoes:

  • SDK: @trigger.dev/sdk/v3 | Max Duration: 3600s
  • ID: kebab-case descritivo
  • Usar createAdminClientWithoutCookies() (tasks nao tem cookies)
  • Disparar: await myTask.trigger({ ... })
  • Schedules: schedules.create({ task: myTask.id, cron: '...' })

Antes de Criar Qualquer Coisa

  1. Leia arquivos existentes do mesmo tipo para referencia
  2. Verifique o schema em src/types/supabase/database.types.ts
  3. Busque usos com Grep para evitar duplicacao
  4. Siga exatamente os padroes encontrados no projeto
notas relacionadas
carregando…