Receber por email
← Voltar para o catálogo

backend-agent

Handles backend/API/database work for Unite-Hub. Implements Next.js API routes, Supabase database operations, RLS policies, authentication, and third-party integrations (Gmail, Stripe).

367estrelas
Atualizado há 4 meses

Ver no GitHub ↗

Como adicionar

/plugin marketplace add aiskillstore/marketplace

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/backend-agent/svg)](https://www.skillteca.com.br/skills/backend-agent)

Skills relacionadas

Ver todas de Segurança →

Alerta por categoria

Receba novas skills de Segurança toda segunda

1 email curto, só com as skills novas de Segurança. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Backend Agent Skill

Overview

The Backend Agent is responsible for all server-side work in Unite-Hub:

  1. Next.js API route development (serverless functions)
  2. Supabase database operations (queries, mutations, RLS)
  3. Authentication and authorization (NextAuth.js, Supabase Auth)
  4. Third-party integrations (Gmail API, Stripe, Claude AI)
  5. Database schema management (migrations, indexes)
  6. API security and performance (rate limiting, caching)

How to Use This Agent

Trigger

User says: "Create new API endpoint", "Fix database query", "Update RLS policies", "Implement Gmail integration"

What the Agent Does

1. Understand the Request

Questions to Ask:

  • What's the API endpoint purpose?
  • What database tables are involved?
  • What's the expected input/output format?
  • What authentication is required?
  • What's the priority (P0/P1/P2)?

2. Analyze Current Implementation

Step A: Locate Files

# Find API routes
find src/app/api -name "route.ts" | grep -i "contacts"

# Find database utilities
find src/lib -name "*.ts" | grep -i "db"

Step B: Read Current Code

// Use text_editor tool
text_editor.view("src/app/api/contacts/route.ts")
text_editor.view("src/lib/db.ts")

Step C: Identify Dependencies

  • What database tables are queried?
  • What authentication is required?
  • What external APIs are called?
  • What error handling exists?

3. Implement Changes

Step A: Create API Route

All API routes in Unite-Hub follow this pattern:

// src/app/api/example/route.ts
import { NextRequest, NextResponse } from "next/server";
import { createClient } from "@/lib/supabase";

export async function POST(request: NextRequest) {
  try {
    // 1. Parse request body
    const body = await request.json();
    const { workspaceId, action, ...params } = body;

    // 2. Validate input
    if (!workspaceId) {
      return NextResponse.json(
        { error: "workspaceId is required" },
        { status: 400 }
      );
    }

    // 3. Get Supabase client
    const supabase = createClient();

    // 4. Check authentication (if needed)
    const { data: { user }, error: authError } = await supabase.auth.getUser();
    if (authError || !user) {
      return NextResponse.json(
        { error: "Unauthorized" },
        { status: 401 }
      );
    }

    // 5. Perform database operation
    const { data, error } = await supabase
      .from("contacts")
      .select("*")
      .eq("workspace_id", workspaceId)  // CRITICAL: Workspace filter
      .eq("organization_id", user.organization_id);  // CRITICAL: Org filter

    if (error) {
      console.error("Database error:", error);
      return NextResponse.json(
        { error: "Database query failed" },
        { status: 500 }
      );
    }

    // 6. Return success response
    return NextResponse.json({
      success: true,
      data,
      count: data.length
    });

  } catch (error) {
    console.error("API error:", error);
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 }
    );
  }
}

// Support OPTIONS for CORS
export async function OPTIONS(request: NextRequest) {
  return NextResponse.json({}, { status: 200 });
}

Step B: Database Operations

All database operations MUST use workspace filtering:

// ❌ BAD - No workspace filter
const { data } = await supabase
  .from("contacts")
  .select("*");

// ✅ GOOD - Workspace filtered
const { data } = await supabase
  .from("contacts")
  .select("*")
  .eq("workspace_id", workspaceId)
  .eq("organization_id", orgId);

Required filters for data isolation:

  • .eq("workspace_id", workspaceId) - Workspace scope
  • .eq("organization_id", orgId) - Organization scope (top-level)

Step C: Update src/lib/db.ts Wrapper

The db.ts wrapper provides consistent database access:

// src/lib/db.ts
import { createClient } from "@/lib/supabase";

export const db = {
  contacts: {
    async listByWorkspace(workspaceId: string) {
      const supabase = createClient();
      const { data, error } = await supabase
        .from("contacts")
        .select("*")
        .eq("workspace_id", workspaceId)
        .order("created_at", { ascending: false });

      if (error) throw error;
      return data || [];
    },

    async getById(contactId: string, workspaceId: string) {
      const supabase = createClient();
      const { data, error } = await supabase
        .from("contacts")
        .select("*")
        .eq("id", contactId)
        .eq("workspace_id", workspaceId)
        .single();

      if (error) throw error;
      return data;
    },

    async create(contact: ContactInput, workspaceId: string) {
      const supabase = createClient();
      const { data, error } = await supabase
        .from("contacts")
        .insert([{ ...contact, workspace_id: workspaceId }])
        .select()
        .single();

      if (error) throw error;
      return data;
    },

    async update(contactId: string, updates: Partial<ContactInput>, workspaceId: string) {
      const supabase = createClient();
      const { data, error } = await supabase
        .from("contacts")
        .update(updates)
        .eq("id", contactId)
        .eq("workspace_id", workspaceId)
        .select()
        .single();

      if (error) throw error;
      return data;
    }
  },

  // Similar patterns for campaigns, emails, etc.
};

CRITICAL FIX for V1: Add missing import in src/lib/db.ts:58

// Line 1 - Add import
import { createClient, getSupabaseServer } from "./supabase";

// Line 58 - Fix usage
const supabaseServer = getSupabaseServer();
const { data: workspace, error } = await supabaseServer
  .from("workspaces")
  .select("*")
  .eq("id", workspaceId)
  .single();

4. Implement Authentication

Pattern 1: Client-Side Auth (Browser)

import { createClient } from "@/lib/supabase";

export async function GET(request: NextRequest) {
  const supabase = createClient();

  const { data: { user }, error } = await supabase.auth.getUser();

  if (error || !user) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  // User is authenticated, proceed
}

Pattern 2: Server-Side Auth (API Routes)

import { getSupabaseServer } from "@/lib/supabase";

export async function POST(request: NextRequest) {
  const supabase = getSupabaseServer();

  const { data: { session }, error } = await supabase.auth.getSession();

  if (error || !session) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  // Session is valid, proceed
}

CRITICAL for V1: Re-enable authentication on all API routes

Many routes currently have:

// TODO: Re-enable authentication in production
// const { auth } = await import("@/lib/auth");
// const session = await auth();

Action Required: Remove TODO comments and re-enable auth checks.

5. Row Level Security (RLS) Policies

All Supabase tables MUST have RLS policies:

-- Enable RLS on table
ALTER TABLE contacts ENABLE ROW LEVEL SECURITY;

-- Policy: Users can only see contacts in their workspace
CREATE POLICY "Users can view workspace contacts"
ON contacts
FOR SELECT
USING (
  workspace_id IN (
    SELECT w.id
    FROM workspaces w
    JOIN user_organizations uo ON uo.organization_id = w.organization_id
    WHERE uo.user_id = auth.uid()
  )
);

-- Policy: Users can insert contacts in their workspace
CREATE POLICY "Users can create workspace contacts"
ON contacts
FOR INSERT
WITH CHECK (
  workspace_id IN (
    SELECT w.id
    FROM workspaces w
    JOIN user_organizations uo ON uo.organization_id = w.organization_id
    WHERE uo.user_id = auth.uid()
  )
);

-- Policy: Users can update contacts in their workspace
CREATE POLICY "Users can update workspace contacts"
ON contacts
FOR UPDATE
USING (
  workspace_id IN (
    SELECT w.id
    FROM wor
Compartilhar X LinkedIn