mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 10:19:43 +00:00
4.4 KiB
4.4 KiB
Supabase - Agent Guidelines
STRICT RULES - DO NOT VIOLATE
Architecture
This contains Supabase configuration:
- Migrations: SQL migrations in
migrations/ - Edge Functions: Deno functions in
functions/ - Email Templates: Auth email templates in
email-templates/ - Config: Local development config in
config.toml
Directory Structure
functions/
delete-relationship/ # Delete couple relationship
manage-couple/ # Join/leave couple
revenuecat-webhook/ # Subscription webhook handler
send-message-notification/ # Push notification for messages
send-notification/ # Push notification for matches
submit-response/ # Save response, check matches
sync-subscription/ # Sync RevenueCat status
migrations/ # SQL migrations
email-templates/ # Auth email templates
config.toml # Local dev configuration
Critical Rules
Edge Function Deployment
ALWAYS use verify_jwt: false when deploying via MCP tools.
Supabase's built-in JWT verification causes 401 errors. Handle auth manually:
const { data: { user }, error: authError } = await supabase.auth.getUser(
authHeader.replace("Bearer ", "")
);
Edge Function Pattern
All edge functions MUST follow this structure:
import "jsr:@supabase/functions-js/edge-runtime.d.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};
Deno.serve(async (req) => {
// Handle CORS preflight
if (req.method === "OPTIONS") {
return new Response("ok", { headers: corsHeaders });
}
try {
const supabase = createClient(
Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!
);
// Manual auth verification
const authHeader = req.headers.get("Authorization");
if (!authHeader) {
return new Response(
JSON.stringify({ error: "Missing authorization header" }),
{ status: 401, headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
}
const { data: { user }, error: authError } = await supabase.auth.getUser(
authHeader.replace("Bearer ", "")
);
// ... function logic
} catch (error) {
return new Response(
JSON.stringify({ error: "Internal server error" }),
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
}
});
Function Auth Methods
| Function | Auth Method |
|---|---|
manage-couple |
Manual via getUser() |
submit-response |
Manual via getUser() |
sync-subscription |
Manual via getUser() |
delete-relationship |
Manual via getUser() |
revenuecat-webhook |
Webhook signature validation |
send-notification |
Internal trigger (no auth) |
send-message-notification |
Internal trigger (no auth) |
Migration Rules
- Use
apply_migrationMCP tool for DDL operations - Never hardcode generated IDs in data migrations
- Always verify target environment (prod vs non-prod) before running
Database Patterns
- Use UPSERT with
onConflictfor responses:onConflict: "user_id,question_id" - Use UPSERT for matches:
onConflict: "couple_id,question_id" - RLS policies enforce couple-level data isolation
Profile Creation
The on_auth_user_created trigger automatically creates a profile. Never assume a profile exists without checking - check for null before operations.
MCP Environments
| Environment | MCP Server |
|---|---|
| Production | mcp__sauci-prod__* |
| Non-Production | mcp__sauci-non-prod__* |
ALWAYS verify environment before destructive operations.
Forbidden Actions
- DO NOT use
verify_jwt: truewhen deploying functions via MCP - DO NOT skip CORS headers in responses
- DO NOT use service role key on client-side
- DO NOT hardcode IDs in migrations
- DO NOT assume profiles exist - always check for null
- DO NOT run migrations on production without explicit confirmation
- DO NOT expose internal error details in responses