> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Pre-Migration Test Plan: Supabase Cloud Migration

> > Version: 1.0.0 > Last Updated: 2026-01-15 > Status: Active

> **Version:** 1.0.0\
> **Last Updated:** 2026-01-15\
> **Status:** Active

## Overview

Test plan for verifying Supabase branching and Vercel integration before completing migration from Lovable Cloud to Supabase Cloud.

### Purpose

* Verify data isolation between staging and production branches
* Confirm migration flow (schema changes merge, data does not)
* Validate Vercel environment variable configuration
* Ensure seed data safety mechanisms work correctly

### Scope

| In Scope                         | Out of Scope                      |
| -------------------------------- | --------------------------------- |
| Supabase branching configuration | Application functionality testing |
| Data isolation verification      | Performance testing               |
| Vercel environment variables     | Security penetration testing      |
| Seed file safety checks          | Load testing                      |
| Migration merge flow             | End-to-end feature testing        |

***

## Architecture Overview

```
┌─────────────────────────────────────────────────────────────────┐
│                        Git Repository                            │
├─────────────────┬──────────────────┬────────────────────────────┤
│   main branch   │  staging branch  │    feature branches        │
└────────┬────────┴────────┬─────────┴──────────┬─────────────────┘
         │                 │                    │
         ▼                 ▼                    ▼
┌─────────────────────────────────────────────────────────────────┐
│                     Vercel Deployments                           │
├─────────────────┬──────────────────┬────────────────────────────┤
│   Production    │     Staging      │       Preview              │
│ encoreos...app│ encoreos...dev │   auto-generated URL       │
└────────┬────────┴────────┬─────────┴──────────┬─────────────────┘
         │                 │                    │
         │ prod anon key   │ staging anon key   │ staging anon key
         ▼                 ▼                    ▼
┌─────────────────────────────────────────────────────────────────┐
│           Supabase Project: zkgxozahyczcnzpwhbbf                 │
├─────────────────┬───────────────────────────────────────────────┤
│  Production DB  │            Staging Branch DB                   │
│  (main project) │   (isolated data, shared schema when merged)   │
└─────────────────┴───────────────────────────────────────────────┘
```

### Key Points

1. **Same Project URL**: All environments use `https://zkgxozahyczcnzpwhbbf.supabase.co` (expected for branching)
2. **Different Anon Keys**: Each branch has unique API keys (critical for isolation)
3. **Data Isolation**: Staging data never transfers to production
4. **Schema Sync**: Migrations merge from staging to production on PR merge

***

## Prerequisites Checklist

Before running tests, verify these items in the respective dashboards:

### Supabase Dashboard Verification

* [ ] **Branching Enabled**: Project has branching feature enabled
* [ ] **Staging Branch Exists**: Persistent branch named "staging" is active
* [ ] **Branch Status**: Staging branch shows "ACTIVE\_HEALTHY" status
* [ ] **API Keys Different**:
  * Production anon key: `eyJ...` (ends differently than staging)
  * Staging anon key: `eyJ...` (ends differently than production)

### Vercel Dashboard Verification

* [ ] **Project Connected**: `cloud-migration-path` project exists
* [ ] **Environment Variables Set**:
  * `VITE_SUPABASE_URL` (same for all environments - correct)
  * `VITE_SUPABASE_ANON_KEY` (different per environment)
  * `VITE_APP_ENV` (`production`, `staging`, `preview`)
* [ ] **Deployment Active**: Latest deployment shows "READY" status

### GitHub Verification

* [ ] **Branch Protection**: `main` branch has protection rules
* [ ] **Staging Branch**: `staging` branch exists and is synced
* [ ] **GitHub Integration**: Supabase GitHub integration is connected

***

## Test Cases

### T001: Data Isolation - Seed Data in Staging Only

**Objective**: Verify seed data applied to staging does not appear in production.

**Preconditions**:

* Staging branch is active
* Seed files exist in `supabase/seeds/`

**Test Steps**:

1. Apply seed data to staging:
   ```bash theme={null}
   npx supabase db seed --linked
   ```

2. Verify seed data exists in staging:
   ```sql theme={null}
   -- Run against STAGING
   SELECT COUNT(*) FROM pf_organizations WHERE id::text LIKE '00000000-%';
   -- Expected: > 0 (seed organizations exist)
   ```

3. Verify seed data does NOT exist in production:
   ```sql theme={null}
   -- Run against PRODUCTION
   SELECT COUNT(*) FROM pf_organizations WHERE id::text LIKE '00000000-%';
   -- Expected: 0 (no seed organizations)
   ```

**Expected Result**: Staging has seed data, production has zero seed records.

**Pass/Fail Criteria**:

* PASS: Production seed count = 0, Staging seed count > 0
* FAIL: Any seed data appears in production

***

### T002: Migration Flow - Schema Changes Merge

**Objective**: Verify schema changes from staging are applied to production on merge.

**Preconditions**:

* Feature branch with new migration exists
* Staging branch is synced with feature branch

**Test Steps**:

1. Create a test migration in staging:
   ```sql theme={null}
   -- Create test table (will be removed after test)
   CREATE TABLE IF NOT EXISTS public.test_migration_verify (
     id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
     test_data TEXT,
     created_at TIMESTAMPTZ DEFAULT NOW()
   );
   ```

2. Commit migration to staging Git branch

3. Verify table exists in staging:
   ```sql theme={null}
   SELECT EXISTS (
     SELECT FROM pg_tables WHERE tablename = 'test_migration_verify'
   );
   -- Expected: true
   ```

4. Create PR from staging to main and merge

5. Verify table now exists in production:
   ```sql theme={null}
   SELECT EXISTS (
     SELECT FROM pg_tables WHERE tablename = 'test_migration_verify'
   );
   -- Expected: true
   ```

6. Clean up: Create migration to drop test table

**Expected Result**: Schema changes propagate from staging to production on merge.

**Pass/Fail Criteria**:

* PASS: Table appears in production after merge
* FAIL: Table does not appear, or appears before merge

***

### T003: Migration Flow - Data Does Not Merge

**Objective**: Verify data inserted in staging does NOT transfer to production.

**Preconditions**:

* T002 has passed (test table exists in both environments)

**Test Steps**:

1. Insert test data in staging:
   ```sql theme={null}
   -- Run against STAGING
   INSERT INTO test_migration_verify (test_data) VALUES ('staging_test_data');
   ```

2. Verify data exists in staging:
   ```sql theme={null}
   -- Run against STAGING
   SELECT COUNT(*) FROM test_migration_verify WHERE test_data = 'staging_test_data';
   -- Expected: 1
   ```

3. Verify data does NOT exist in production:
   ```sql theme={null}
   -- Run against PRODUCTION
   SELECT COUNT(*) FROM test_migration_verify WHERE test_data = 'staging_test_data';
   -- Expected: 0
   ```

**Expected Result**: Data remains isolated in staging branch.

**Pass/Fail Criteria**:

* PASS: Production has 0 test records, staging has 1
* FAIL: Any test data appears in production

***

### T004: Vercel Integration - Correct API Keys Per Environment

**Objective**: Verify Vercel deployments connect to correct Supabase environment.

**Preconditions**:

* Production deployment is live
* Staging deployment is live (or preview deployment exists)

**Test Steps**:

1. Access production deployment:
   * URL: `https://northsightrecovery.app` or production Vercel URL
   * Open browser DevTools → Network tab
   * Observe API requests to Supabase

2. Verify production anon key in requests:
   * Check `Authorization: Bearer <token>` header
   * Token should match production anon key

3. Access staging deployment:
   * URL: `https://northsightrecovery.dev` or staging Vercel URL
   * Open browser DevTools → Network tab

4. Verify staging anon key in requests:
   * Token should be DIFFERENT from production

**Expected Result**: Different anon keys used per environment.

**Pass/Fail Criteria**:

* PASS: Anon keys are different between environments
* FAIL: Same anon key used in both environments

***

### T005: Seed Safety - Production Detection Works

**Objective**: Verify seed files have safety checks that prevent accidental production seeding.

**Preconditions**:

* Seed files exist with safety checks
* Access to test against production (carefully!)

**Test Steps**:

1. Review seed file safety check:
   ```sql theme={null}
   -- Expected pattern in seed files
   DO $$
   BEGIN
     IF EXISTS (
       SELECT 1 FROM pf_organizations 
       WHERE id NOT LIKE '00000000-%'
       LIMIT 1
     ) THEN
       RAISE WARNING 'Real data detected. Ensure you are connected to staging.';
     END IF;
   END $$;
   ```

2. Verify safety check is present in all seed files:
   ```bash theme={null}
   grep -l "Real data detected" supabase/seeds/**/*.sql
   ```

3. If production has real data, attempt to run seed (will warn/fail)

**Expected Result**: Seed files detect non-seed data and warn/fail.

**Pass/Fail Criteria**:

* PASS: Safety check present and functional
* FAIL: No safety check or check bypassed

***

### T006: RLS Verification - Tenant Isolation Active

**Objective**: Verify Row Level Security policies are active for tenant isolation.

**Preconditions**:

* Database schema is deployed

**Test Steps**:

1. Count tables with RLS enabled:
   ```sql theme={null}
   SELECT COUNT(*) FROM pg_tables 
   WHERE schemaname = 'public' AND rowsecurity = true;
   -- Expected: > 400 (most tables have RLS)
   ```

2. Verify critical tables have RLS:
   ```sql theme={null}
   SELECT tablename, rowsecurity FROM pg_tables 
   WHERE schemaname = 'public' 
   AND tablename IN ('pf_organizations', 'hr_employees', 'fa_accounts')
   ORDER BY tablename;
   -- Expected: All show rowsecurity = true
   ```

**Expected Result**: RLS enabled on all business tables.

**Pass/Fail Criteria**:

* PASS: All critical tables have RLS enabled
* FAIL: Any critical table missing RLS

***

## Current Database State (Verified via MCP)

**Date Verified**: 2026-01-15

### Staging Branch Status

| Check                  | Result                                      | Status              |
| ---------------------- | ------------------------------------------- | ------------------- |
| Recent Migrations      | 10 migrations visible (including RLS fixes) | ✅                   |
| Seed Data Present      | 0 organizations with seed IDs               | ✅ Clean             |
| Real Data Present      | 0 organizations with real IDs               | ✅ Clean             |
| RLS Enabled Tables     | 452 tables                                  | ✅                   |
| pf\_organizations rows | 0                                           | ✅ Ready for seeding |
| hr\_employees rows     | 0                                           | ✅ Ready for seeding |

### Key Tables Available

* `pf_organizations` - Platform organizations
* `hr_employees` - HR employees
* `hr_*` - 50+ HR module tables
* `rh_*` - Recovery Housing tables (rh\_alumni, rh\_beds, etc.)
* `fa_*` - Finance module tables
* `fw_*` - Forms/Workflow tables

***

## Rollback Procedures

### If Seed Data Accidentally Applied to Production

1. **Immediate Action**: Do NOT merge any branches
2. **Identify seed records**:
   ```sql theme={null}
   SELECT * FROM pf_organizations WHERE id::text LIKE '00000000-%';
   ```
3. **Delete seed records** (if safe):
   ```sql theme={null}
   DELETE FROM pf_organizations WHERE id::text LIKE '00000000-%';
   ```
4. **Verify cleanup**:
   ```sql theme={null}
   SELECT COUNT(*) FROM pf_organizations WHERE id::text LIKE '00000000-%';
   -- Should return 0
   ```

### If Migration Causes Issues

1. **Do NOT panic** - Supabase branches are isolated
2. **For staging**: Reset the branch
   ```bash theme={null}
   supabase branches reset <branch-id>
   ```
3. **For production**: Create rollback migration
   ```bash theme={null}
   supabase migration new rollback_issue
   # Write reverse DDL statements
   ```

### If Vercel Environment Variables Wrong

1. Go to Vercel Dashboard → Project → Settings → Environment Variables
2. Update incorrect variable
3. Trigger redeploy:
   ```bash theme={null}
   vercel --prod  # for production
   vercel         # for preview
   ```

***

## Sign-Off Checklist

Before proceeding with production migration, all items must be checked:

### Pre-Migration Sign-Off

* [ ] All test cases (T001-T006) have passed
* [ ] Staging branch has seed data (T001)
* [ ] Production has no seed data (T001)
* [ ] Schema changes merge correctly (T002)
* [ ] Data stays isolated (T003)
* [ ] Vercel uses correct keys (T004)
* [ ] Seed safety checks work (T005)
* [ ] RLS is active on all tables (T006)

### Final Approvals

| Role      | Name | Date | Signature |
| --------- | ---- | ---- | --------- |
| Tech Lead |      |      |           |
| DevOps    |      |      |           |
| QA Lead   |      |      |           |

***

## Related Documentation

* [Pre-Migration Checklist](./PRE_MIGRATION_CHECKLIST.md) - Manual verification steps
* [Vercel Integration Guide](../integrations/VERCEL_INTEGRATION.md) - Vercel configuration
* Supabase MCP Usage - MCP tool reference
* [Migration Completion Plan](../migration/COMPLETION_PLAN.md) - Overall migration plan
* [Seed Files README](../../supabase/seeds/README.md) - Seed file documentation

***

## Appendix: SQL Verification Queries

All queries used in this test plan are available in:
`scripts/verify-data-isolation.sql`

### Quick Reference Queries

```sql theme={null}
-- Check staging is clean (no seed data)
SELECT COUNT(*) FROM pf_organizations WHERE id::text LIKE '00000000-%';

-- Count RLS-enabled tables
SELECT COUNT(*) FROM pg_tables WHERE schemaname = 'public' AND rowsecurity = true;

-- View recent migrations
SELECT version, name FROM supabase_migrations.schema_migrations ORDER BY version DESC LIMIT 10;

-- Check table exists
SELECT EXISTS (SELECT FROM pg_tables WHERE tablename = 'your_table_name');
```
