# Supabase Key Rotation Guide

## Overview
This guide documents the process for rotating Supabase API keys (anon and service role) for the RateRight v2 application. Regular key rotation is a security best practice that should be performed periodically (recommended every 90 days) or immediately if keys are suspected to be compromised.

## Current Key Status
- **Anon Key**: Exposed in documentation (CLAUDE.md) - needs rotation
- **Service Role Key**: Not yet configured - needs to be added
- **Last Rotation**: Unknown (initial keys from project creation)

## Step 1: Generate New Keys in Supabase Dashboard

### 1.1 Access Supabase Dashboard
1. Go to [Supabase Dashboard](https://app.supabase.com)
2. Select the `memscjotxrzqnhrvnnkc` project (RateRight v2)
3. Navigate to **Settings → API**

### 1.2 Generate New Anon Key
1. In the **Project API keys** section, find the "anon public" key
2. Click **"Regenerate"** next to the anon key
3. **IMPORTANT**: Copy the new key immediately (it won't be shown again)
4. The anon key starts with `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9`

### 1.3 Generate New Service Role Key
1. In the same section, find the "service_role" key
2. Click **"Regenerate"** next to the service role key
3. **IMPORTANT**: Copy the new key immediately (it won't be shown again)
4. The service role key also starts with `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9`
5. **SECURITY NOTE**: The service role key has admin privileges. Never expose it publicly.

## Step 2: Update Environment Variables

### 2.1 Update `.env.local`
Update the following variables in `/home/ccuser/the-50-dollar-app/.env.local`:

```bash
# Supabase credentials
NEXT_PUBLIC_SUPABASE_URL=https://memscjotxrzqnhrvnnkc.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_new_anon_key_here
SUPABASE_SERVICE_ROLE_KEY=your_new_service_role_key_here

# Other environment variables remain unchanged
ABR_GUID=REGISTER-TOMORROW-AT-ABR-BUSINESS-GOV-AU
OPENAI_API_KEY=your_openai_api_key_here
```

### 2.2 Verify File Permissions
Ensure `.env.local` has proper permissions:
```bash
chmod 600 /home/ccuser/the-50-dollar-app/.env.local
```

## Step 3: Update Application Code

### 3.1 Service Role Client Implementation
The service role client has been implemented in `src/lib/supabase/server.ts`:

```typescript
export function createServiceClient() {
  if (!process.env.SUPABASE_SERVICE_ROLE_KEY) {
    throw new Error(
      "SUPABASE_SERVICE_ROLE_KEY is not set in environment variables. " +
      "Add it to .env.local from Supabase Dashboard → Settings → API → service_role key"
    );
  }

  return createSupabaseClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!,
    {
      auth: {
        autoRefreshToken: false,
        persistSession: false,
      },
    }
  );
}
```

### 3.2 Create Payments API Endpoint (Required for RLS Fix)
Create `src/app/api/payments/create/route.ts`:

```typescript
import { createServiceClient } from '@/lib/supabase/server';
import { createClient } from '@/lib/supabase/server';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  try {
    const supabase = createClient();
    const {
      data: { user },
    } = await supabase.auth.getUser();
    
    if (!user) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const body = await request.json();
    const { match_id, company_id, amount } = body;

    // Verify user owns the company
    const { data: company } = await supabase
      .from('companies')
      .select('id')
      .eq('id', company_id)
      .eq('profile_id', user.id)
      .single();

    if (!company) {
      return NextResponse.json({ error: 'Company not found or unauthorized' }, { status: 403 });
    }

    // Verify match is hired and belongs to company's job
    const { data: match } = await supabase
      .from('matches')
      .select('status, jobs!inner(company_id)')
      .eq('id', match_id)
      .eq('status', 'hired')
      .eq('jobs.company_id', company_id)
      .single();

    if (!match) {
      return NextResponse.json({ error: 'Match not found, not hired, or unauthorized' }, { status: 403 });
    }

    // Create payment using service role
    const supabaseService = createServiceClient();
    const { data: payment, error } = await supabaseService
      .from('payments')
      .insert({
        match_id,
        company_id,
        amount: amount || 50.0,
        status: 'pending',
      })
      .select()
      .single();

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

    return NextResponse.json({ payment });
  } catch (error) {
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
  }
}
```

### 3.3 Update Contractor Matches Page
Update `src/app/contractor/matches/page.tsx` to use the API endpoint instead of direct Supabase insert:

```typescript
// Replace the direct payment insert (lines 427-432) with:
const response = await fetch('/api/payments/create', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    match_id: match.id,
    company_id: company.id,
    amount: 50.0
  })
});

if (!response.ok) {
  const error = await response.json();
  toast.error(`Payment creation failed: ${error.error}`);
  setHiring(null);
  return;
}
```

## Step 4: Apply RLS Migration

### 4.1 Apply the RLS Fix Migration
Run the SQL migration from `supabase/fix-critical-rls-insert-policies.sql` in the Supabase SQL Editor.

### 4.2 Verify Policies
After applying the migration, verify the new policies with:

```sql
SELECT 
  tablename,
  policyname,
  cmd,
  qual,
  with_check
FROM pg_policies 
WHERE tablename IN ('matches', 'payments')
ORDER BY tablename, policyname;
```

## Step 5: Test the Application

### 5.1 Test Authentication
- Sign up as a new user
- Log in with existing user
- Verify session persistence

### 5.2 Test Worker Flow
- Worker applies for a job
- Verify match record is created with status 'applied'

### 5.3 Test Contractor Flow
- Contractor hires a worker
- Verify payment is created via API
- Verify payment record has correct company_id

### 5.4 Test Error Cases
- Try to insert payment as regular user (should fail)
- Try to insert match for another user (should fail)

## Step 6: Clean Up Documentation

### 6.1 Remove Exposed Keys
- ✅ Already removed from `CLAUDE.md`
- Ensure no keys are in any other documentation files

### 6.2 Update README
- ✅ README.md already uses placeholders
- No changes needed

## Step 7: Monitor and Verify

### 7.1 Monitor Application Logs
- Watch for authentication errors
- Monitor for authorization failures

### 7.2 Verify Key Usage
- Confirm new anon key is being used (check network requests)
- Confirm service role key is only used server-side

## Emergency Rollback Procedure

If the key rotation breaks the application:

### 7.1 Immediate Rollback
1. Revert to old keys in `.env.local`
2. Disable new RLS policies (use rollback script in migration)
3. Restore direct payment inserts in frontend code

### 7.2 Investigation
1. Check browser console for errors
2. Check server logs for authentication failures
3. Verify environment variables are loaded correctly

### 7.3 Re-attempt Rotation
1. Identify the specific issue
2. Fix the problem
3. Re-attempt rotation with corrected implementation

## Security Best Practices

### Regular Rotation Schedule
- **Anon Key**: Rotate every 90 days
- **Service Role Key**: Rotate every 180 days
- **Emergency Rotation**: Immediately if keys are exposed

### Key Management
- Never commit keys to version control
- Use environment variables for all secrets
- Restrict access to `.env.local` file
- Use different keys for different environments (dev/staging/prod)

### Monitoring
- Set up alerts for authentication failures
- Monitor for unusual API usage patterns
- Regularly audit key usage and permissions

## Troubleshooting

### Common Issues

#### "Invalid API key" errors
1. Verify the key is correctly copied (no extra spaces)
2. Check if the key has been regenerated in Supabase
3. Verify environment variable name matches code

#### Service role key not working
1. Verify `SUPABASE_SERVICE_ROLE_KEY` is in `.env.local`
2. Check that the service role client is being used correctly
3. Verify the key has not expired or been revoked

#### RLS policy violations
1. Check that API endpoints are using service role for authorized operations
2. Verify user authentication is working
3. Check that the migration was applied correctly

## Next Steps After Rotation

1. **Update all environments**: Apply same rotation to staging/production
2. **Document rotation date**: Record in security log
3. **Schedule next rotation**: Set calendar reminder for 90 days
4. **Review access logs**: Ensure no unauthorized access with old keys

## Contact Information

For security issues or emergency key rotation:
- **Primary Contact**: Michael McLoughlin
- **Backup Contact**: System Administrator

---

**Last Updated**: 2026-02-07  
**Last Rotation**: [Date after successful rotation]  
**Next Scheduled Rotation**: [Date + 90 days]