Created: 2026-02-16 Status: ✅ COMPLETE - All 47 Tests Implemented Tool: Playwright MCP Last Updated: 2026-02-16
Test Files Created:
- ✅
tests/playwright/multi-tenant-isolation.spec.ts(8 tests) - ✅
tests/playwright/authentication-security.spec.ts(6 tests) - ✅
tests/playwright/payment-security.spec.ts(7 tests) - ✅
tests/playwright/comprehensive-security-audit.spec.ts(26 tests)
Total: 47 comprehensive E2E tests
Documentation:
- ✅
TEST_EXECUTION_GUIDE.md- Complete execution guide - ✅
MULTI_TENANT_IMPLEMENTATION_SUMMARY.md- Full implementation summary
To Execute Tests:
npx playwright testSee TEST_EXECUTION_GUIDE.md for detailed instructions.
This document outlines a comprehensive End-to-End (E2E) testing and security audit plan for the multi-tenant LMS platform. The plan covers 47 critical test scenarios across 8 major categories, focusing on multi-tenancy isolation, authentication security, payment flows, and data protection.
Testing Priorities:
- CRITICAL: Multi-tenant data isolation (prevent cross-tenant leaks)
- CRITICAL: Authentication & authorization flows
- CRITICAL: Payment security (Stripe Connect, manual payments)
- HIGH: Revenue infrastructure (splits, payouts, refunds)
- HIGH: Join school flow and tenant switching
- MEDIUM: Onboarding wizard and plan limits
- MEDIUM: Dashboard access controls
- LOW: UI/UX validation
Priority: P0 - Security Critical Total Tests: 8
Objective: Verify students cannot access courses from other tenants
Test Steps:
- Create School A with course "Math 101"
- Create School B with course "Science 201"
- Create student account at School A
- Enroll student in "Math 101" at School A
- Try to access "Science 201" from School B via direct URL
- Try to enroll in School B course via API call
Expected Results:
- ✅ Student can access "Math 101" from School A
- ✅ Student CANNOT access "Science 201" from School B
- ✅ API enrollment call fails with 404 or 403
- ✅ No cross-tenant data visible in dashboard
- ✅ Database queries filtered by tenant_id
Security Risk: HIGH - Data breach, unauthorized course access
Objective: Verify admin/teacher at School A cannot see users from School B
Test Steps:
- Create School A with 10 students
- Create School B with 10 different students
- Login as admin at School A
- Navigate to /dashboard/admin/users
- Inspect user list API response
- Try to access School B student profile directly
Expected Results:
- ✅ Admin sees only School A's 10 students
- ✅ School B students not in API response
- ✅ Direct access to School B student profile fails
- ✅ User count shows only School A users
- ✅ No cross-tenant user_id leaks
Security Risk: HIGH - PII exposure, GDPR violation
Objective: Verify revenue data is isolated per tenant
Test Steps:
- School A has 5 transactions ($500 total)
- School B has 3 transactions ($300 total)
- Login as admin at School A
- Navigate to /dashboard/admin/transactions
- Navigate to /dashboard/teacher/revenue
- Inspect API responses for transaction data
Expected Results:
- ✅ School A admin sees only 5 transactions
- ✅ Revenue dashboard shows $500 (not $800)
- ✅ Transaction IDs are from School A only
- ✅ No School B payment data visible
- ✅ Database queries include tenant_id filter
Security Risk: CRITICAL - Financial data leak, compliance violation
Objective: Verify products and plans are tenant-scoped
Test Steps:
- School A creates product "Math Course" ($100)
- School B creates product "Science Course" ($150)
- Student visits School A's /pricing page
- Student visits School B's /pricing page
- Try to purchase School B product while logged into School A
Expected Results:
- ✅ School A pricing shows only "Math Course"
- ✅ School B pricing shows only "Science Course"
- ✅ Cannot purchase cross-tenant products
- ✅ Checkout validates product belongs to current tenant
- ✅ Payment intent creation fails for wrong tenant
Security Risk: CRITICAL - Unauthorized purchases, payment fraud
Objective: Verify enrollments are scoped to tenant
Test Steps:
- School A student enrolls in School A course
- Try to access School B course while authenticated at School A
- Manually create enrollment with wrong tenant_id in database
- Verify RLS policies reject the operation
Expected Results:
- ✅ Enrollment works for same-tenant course
- ✅ Cross-tenant enrollment blocked by middleware
- ✅ Direct database insert blocked by RLS
- ✅ API returns 404 for cross-tenant courses
- ✅ Dashboard shows only same-tenant enrollments
Security Risk: HIGH - Unauthorized course access
Objective: Verify middleware correctly detects tenant from subdomain
Test Steps:
- Visit school-a.localhost:3000
- Visit school-b.localhost:3000
- Check x-tenant-id header in requests
- Verify JWT contains correct tenant_id claim
- Switch between subdomains
Expected Results:
- ✅ school-a subdomain sets tenant_id for School A
- ✅ school-b subdomain sets tenant_id for School B
- ✅ Invalid subdomain redirects to platform root
- ✅ JWT claim matches subdomain tenant
- ✅ Session maintains correct tenant context
Security Risk: CRITICAL - Entire multi-tenancy depends on this
Objective: Verify Row Level Security policies prevent cross-tenant access
Test Steps:
- Get user's session token
- Make direct Supabase client queries
- Try to query courses from other tenant
- Try to query transactions from other tenant
- Try to insert data with wrong tenant_id
Expected Results:
- ✅ SELECT returns only current tenant's data
- ✅ INSERT with wrong tenant_id fails
- ✅ UPDATE cannot modify other tenant's data
- ✅ DELETE cannot remove other tenant's data
- ✅ Service role bypasses RLS (for admin operations)
Security Risk: CRITICAL - Database-level security breach
Objective: Verify leaderboards and XP are tenant-scoped
Test Steps:
- Student at School A earns 1000 XP
- Student at School B earns 500 XP
- View leaderboard at School A
- View leaderboard at School B
- Check XP totals in dashboard
Expected Results:
- ✅ School A leaderboard shows only School A students
- ✅ School B leaderboard independent
- ✅ XP totals don't include cross-tenant data
- ✅ Achievements scoped to tenant
- ✅ Store items filtered by tenant
Security Risk: MEDIUM - Competitive fairness, data mixing
Priority: P0 - Security Critical Total Tests: 6
Objective: Verify login preserves tenant context
Test Steps:
- User signs up at school-a.localhost:3000
- User logs out
- User logs in at school-a.localhost:3000
- Check preferred_tenant_id in JWT
- Verify redirected to correct tenant dashboard
Expected Results:
- ✅ Login sets preferred_tenant_id to School A
- ✅ JWT contains correct tenant_id claim
- ✅ Redirects to school-a dashboard (not school-b)
- ✅ Session cookie domain correct
- ✅ Can access School A resources
Security Risk: HIGH - Session hijacking, wrong tenant access
Objective: Verify password reset maintains tenant subdomain
Test Steps:
- Student at school-a.localhost:3000
- Click "Forgot Password"
- Enter email, submit
- Check reset email link
- Click link, verify stays on school-a subdomain
- Reset password, verify login works
Expected Results:
- ✅ Reset link points to school-a.localhost:3000
- ✅ Not redirected to platform root domain
- ✅ After reset, user logs into School A
- ✅ preferred_tenant_id unchanged
- ✅ Session maintains tenant context
Security Risk: MEDIUM - User confusion, loss of tenant context
Objective: Verify email confirmation sets correct tenant
Test Steps:
- User signs up at school-b.localhost:3000
- Receives confirmation email
- Clicks confirmation link
- Check redirect URL and tenant_id
- Verify user is member of School B
Expected Results:
- ✅ Confirmation link includes school-b subdomain
- ✅ User added to School B's tenant_users
- ✅ preferred_tenant_id set to School B
- ✅ JWT includes School B tenant_id
- ✅ Redirects to School B dashboard
Security Risk: HIGH - User assigned to wrong tenant
Objective: Verify role restrictions work correctly
Test Steps:
- Login as student
- Try to access /dashboard/admin
- Try to access /dashboard/teacher
- Login as teacher
- Try to access /dashboard/admin
- Login as admin
- Access all dashboards
Expected Results:
- ✅ Student redirected from admin/teacher dashboards
- ✅ Teacher can access teacher dashboard
- ✅ Teacher redirected from admin dashboard
- ✅ Admin can access all dashboards
- ✅ API endpoints enforce role checks
Security Risk: HIGH - Privilege escalation
Objective: Verify expired tokens are rejected
Test Steps:
- Login and get session token
- Wait for token to expire (or manipulate timestamp)
- Try to access protected route
- Try to call protected API
- Verify forced logout
Expected Results:
- ✅ Expired token rejected
- ✅ User redirected to login
- ✅ API returns 401 Unauthorized
- ✅ Session cleared
- ✅ Refresh token flow works if valid
Security Risk: MEDIUM - Session security
Objective: Verify super admins can access all tenants
Test Steps:
- Login as super admin
- Visit school-a.localhost:3000
- Access admin dashboard
- View all schools' data
- Switch to school-b.localhost:3000
- Repeat access checks
Expected Results:
- ✅ Super admin can access School A data
- ✅ Super admin can access School B data
- ✅ RLS policies include is_super_admin() check
- ✅ Can switch between tenants freely
- ✅ Cannot be blocked by RLS
Security Risk: HIGH - Must be tightly controlled
Priority: P0 - Financial Security Total Tests: 7
Objective: Verify Stripe Connect routes payments correctly
Test Steps:
- School A connects Stripe account
- School A creates paid course ($100)
- Student purchases course
- Check payment intent includes:
- application_fee_amount (20%)
- transfer_data.destination (School A's account)
- Verify transaction created with correct tenant_id
Expected Results:
- ✅ Payment intent created with $20 platform fee
- ✅ $80 transfers to School A's Stripe account
- ✅ Transaction record has School A's tenant_id
- ✅ Webhook updates transaction status
- ✅ Student enrolled in course
Security Risk: CRITICAL - Financial loss, payment fraud
Objective: Verify error when Stripe not connected
Test Steps:
- School B has not connected Stripe
- School B creates paid course
- Student tries to purchase
- Check error message
Expected Results:
- ✅ Checkout shows error
- ✅ Error: "School has not connected payment account"
- ✅ No payment intent created
- ✅ No transaction record created
- ✅ Student not enrolled
Security Risk: MEDIUM - User confusion, lost sales
Objective: Verify manual payment workflow
Test Steps:
- School creates product with payment_provider='manual'
- Student submits payment request
- Admin sends payment instructions
- Admin confirms payment received
- Admin completes and enrolls student
- Verify enrollment created
Expected Results:
- ✅ Payment request created (status: pending)
- ✅ Admin can send instructions (status: contacted)
- ✅ Admin can confirm payment (status: payment_received)
- ✅ Complete creates transaction (status: successful)
- ✅ Student enrolled in course
Security Risk: MEDIUM - Manual process, potential errors
Objective: Verify refunds cancel enrollments
Test Steps:
- Student purchases course
- Transaction successful, enrolled
- Admin issues refund via Stripe
- Webhook receives charge.refunded event
- Check transaction and enrollment status
Expected Results:
- ✅ Transaction status updated to 'refunded'
- ✅ Enrollment status updated to 'disabled'
- ✅ Student loses access to course
- ✅ Revenue dashboard reflects refund
- ✅ Audit trail preserved
Security Risk: MEDIUM - Customer disputes, fraud
Objective: Verify cannot pay for another tenant's products
Test Steps:
- School A has product (ID: 123)
- Student logged into School B
- Try to purchase product 123 via API
- Try to access checkout with School A product ID
Expected Results:
- ✅ Checkout validates product.tenant_id matches current tenant
- ✅ API returns 404 or 403
- ✅ Payment intent creation fails
- ✅ No transaction created
- ✅ No enrollment created
Security Risk: CRITICAL - Payment fraud, unauthorized access
Objective: Verify platform fee calculated correctly
Test Steps:
- School has custom split (70/30)
- Student purchases $100 course
- Check payment intent application_fee_amount
- Verify transfer amount
- Check revenue dashboard calculations
Expected Results:
- ✅ Platform fee: $30 (30%)
- ✅ Transfer amount: $70 (70%)
- ✅ Revenue dashboard shows $100 total, $70 school share
- ✅ revenue_splits table queried correctly
- ✅ Default 80/20 used if no custom split
Security Risk: HIGH - Financial accuracy
Objective: Verify payout webhooks update database
Test Steps:
- Stripe processes payout to school
- Webhook receives payout.paid event
- Check payouts table updated
- Webhook receives payout.failed event
- Check status updated
Expected Results:
- ✅ payout.paid updates status to 'paid'
- ✅ paid_at timestamp set
- ✅ payout.failed updates status to 'failed'
- ✅ Revenue dashboard shows payout history
- ✅ Correct tenant_id in payout record
Security Risk: MEDIUM - Financial reporting accuracy
Priority: P1 - User Experience Critical Total Tests: 5
Objective: Verify user can join additional schools
Test Steps:
- User already member of School A
- Visit school-b.localhost:3000
- Redirected to /join-school
- Click "Join School B"
- Verify enrollment and access
Expected Results:
- ✅ Middleware detects no membership
- ✅ Auto-redirects to /join-school
- ✅ Shows school info and benefits
- ✅ Join creates tenant_users record
- ✅ Session refreshed with new JWT
- ✅ Can access School B dashboard
Security Risk: MEDIUM - User frustration if broken
Objective: Verify "already a member" message works
Test Steps:
- User is member of School A
- Visit school-a.localhost:3000/join-school
- Check message and buttons
Expected Results:
- ✅ Shows "You're Already a Member!" message
- ✅ Displays school name
- ✅ "Go to Dashboard" and "Browse Courses" buttons
- ✅ No join form shown
- ✅ No duplicate membership created
Security Risk: LOW - UX issue only
Objective: Verify users can switch between schools
Test Steps:
- User has memberships in School A and School B
- Currently on School A
- Click tenant switcher
- Select School B
- Verify redirect and context switch
Expected Results:
- ✅ Switcher shows both schools
- ✅ Current school highlighted
- ✅ Click updates preferred_tenant_id
- ✅ Session refreshed
- ✅ Redirects to school-b.localhost:3000
- ✅ Dashboard shows School B data
Security Risk: MEDIUM - Wrong tenant context
Objective: Verify each school shows independent data
Test Steps:
- User member of School A (enrolled in 3 courses)
- User member of School B (enrolled in 2 courses)
- View School A dashboard
- Switch to School B dashboard
Expected Results:
- ✅ School A dashboard shows 3 courses
- ✅ School B dashboard shows 2 courses
- ✅ No data mixing between schools
- ✅ Progress tracked independently
- ✅ Certificates issued per school
Security Risk: HIGH - Data mixing, user confusion
Objective: Verify redirect to login
Test Steps:
- Not logged in
- Visit school-a.localhost:3000/join-school
- Check redirect
Expected Results:
- ✅ Redirects to /auth/login
- ✅ next parameter set to /join-school
- ✅ After login, returns to join page
- ✅ Can complete join flow
Security Risk: LOW - UX issue
Priority: P2 - Conversion Critical Total Tests: 4
Objective: Verify full onboarding flow
Test Steps:
- New user signs up
- Navigates to /onboarding
- Completes all 5 steps
- Connects Stripe on step 4
- Finishes onboarding
Expected Results:
- ✅ Welcome step shows
- ✅ School info saves to tenant_settings
- ✅ Branding saves (logo, colors)
- ✅ Payment step shows revenue split
- ✅ Stripe Connect redirects work
- ✅ stripe_account_id saved
- ✅ onboarding_completed set to true
- ✅ Redirects to dashboard
Security Risk: LOW - Conversion rate impact
Objective: Verify skip functionality
Test Steps:
- New user at onboarding
- Reach payment step (step 4)
- Click "Skip for Now"
- Complete onboarding
Expected Results:
- ✅ Warning alert shown
- ✅ Can proceed to step 5
- ✅ stripe_account_id remains NULL
- ✅ onboarding_completed = true
- ✅ Revenue dashboard shows connection prompt
Security Risk: LOW - User choice
Objective: Verify 5-step progress indicator
Test Steps:
- Navigate to onboarding
- Check progress dots
- Advance through each step
- Verify dot activation
Expected Results:
- ✅ Shows 5 dots total (not 4)
- ✅ Step 1: 1 dot active
- ✅ Step 4: 4 dots active (payment step)
- ✅ Step 5: All 5 dots active
- ✅ Visual feedback clear
Security Risk: NONE - UI only
Objective: Verify can complete later
Test Steps:
- Start onboarding, complete step 2
- Close browser
- Login again
- Check redirect
Expected Results:
- ✅ onboarding_completed = false
- ✅ Redirected to /onboarding
- ✅ Previous data pre-filled
- ✅ Can continue from any step
- ✅ Can complete successfully
Security Risk: LOW - UX issue
Priority: P2 - Business Logic Critical Total Tests: 4
Objective: Verify free plan limited to 5 courses
Test Steps:
- School on free plan
- Create 5 courses successfully
- Try to create 6th course
- Check error message
Expected Results:
- ✅ Courses 1-5 created successfully
- ✅ Course 6 blocked
- ✅ Error: "Your free plan is limited to 5 courses"
- ✅ UI shows warning at 4/5 (80%)
- ✅ Upgrade prompt displayed
Security Risk: LOW - Business rule enforcement
Objective: Verify basic plan limit
Test Steps:
- Upgrade school to basic plan
- Create 20 courses
- Try to create 21st course
Expected Results:
- ✅ Courses 1-20 created
- ✅ Course 21 blocked
- ✅ Error mentions "basic plan" and "20 courses"
- ✅ Upgrade to professional suggested
Security Risk: LOW - Business rule enforcement
Objective: Verify enterprise has no limit
Test Steps:
- School on enterprise plan
- Create 150 courses
- Verify no errors
Expected Results:
- ✅ All 150 courses created
- ✅ No limit warnings
- ✅ checkCourseLimit returns canCreate: true
- ✅ Infinity limit works
Security Risk: LOW - Business rule
Objective: Verify cannot bypass via API
Test Steps:
- School at 5/5 courses (free plan)
- Try to create course via direct API call
- Try to bypass client-side check
Expected Results:
- ✅ Server action checks limit
- ✅ API returns error
- ✅ Course not created
- ✅ Cannot bypass client-side validation
Security Risk: MEDIUM - Enforcement bypass
Priority: P2 - User Experience Total Tests: 3
Objective: Verify only teachers/admins can access
Test Steps:
- Login as student
- Try to access /dashboard/teacher/revenue
- Login as teacher
- Access revenue dashboard
Expected Results:
- ✅ Student redirected to /dashboard/student
- ✅ Teacher can access revenue page
- ✅ Admin can access revenue page
- ✅ Data shows only current tenant
Security Risk: MEDIUM - Unauthorized data access
Objective: Verify revenue split math
Test Steps:
- School has 5 transactions totaling $500
- Revenue split is 80/20
- Check dashboard calculations
Expected Results:
- ✅ Total revenue: $500
- ✅ Platform fee (20%): $100
- ✅ School revenue (80%): $400
- ✅ Percentages match revenue_splits table
- ✅ Recent revenue (30 days) calculated correctly
Security Risk: LOW - Display accuracy
Objective: Verify warning shown when not connected
Test Steps:
- School without stripe_account_id
- Teacher accesses revenue dashboard
- Check warning display
Expected Results:
- ✅ Alert shown: "Payment Account Not Connected"
- ✅ "Connect Stripe Account" button visible
- ✅ Links to /api/stripe/connect
- ✅ Warning is dismissible or closeable
Security Risk: NONE - UX only
Priority: P0 - Security Assessment Total Tests: 10
Objective: Verify queries are parameterized
Test Steps:
- Try SQL injection in login email:
' OR '1'='1 - Try in course search:
'; DROP TABLE courses;-- - Try in product name:
<script>alert('xss')</script>
Expected Results:
- ✅ All queries use parameterized statements
- ✅ No SQL execution from user input
- ✅ Supabase client automatically escapes
- ✅ RLS policies additional protection
Security Risk: CRITICAL - Database compromise
Objective: Verify user input is sanitized
Test Steps:
- Create course with name:
<script>alert('xss')</script> - Add lesson with content:
<img src=x onerror=alert('xss')> - View course page and lesson
Expected Results:
- ✅ Script tags rendered as text, not executed
- ✅ React escapes HTML by default
- ✅ MDX content safely rendered
- ✅ No alert() popups appear
Security Risk: HIGH - Account takeover, malware
Objective: Verify CSRF tokens on forms
Test Steps:
- Check payment forms
- Check course creation forms
- Try to submit from external site
Expected Results:
- ✅ Forms include CSRF tokens
- ✅ Server validates tokens
- ✅ Cross-origin requests blocked
- ✅ SameSite cookies configured
Security Risk: HIGH - Unauthorized actions
Objective: Verify rate limits on sensitive endpoints
Test Steps:
- Make 100 login attempts in 1 minute
- Make 50 API calls to create courses
- Check if blocked
Expected Results:
- ✅ Rate limiting active on auth endpoints
- ✅ Rate limiting on payment endpoints
- ✅ 429 Too Many Requests returned
- ✅ Retry-After header provided
Security Risk: MEDIUM - Brute force, DDoS
Objective: Verify no sensitive data in client
Test Steps:
- Check API responses
- Check localStorage/sessionStorage
- Check browser console logs
- Inspect network tab
Expected Results:
- ✅ No service role keys in client
- ✅ No Stripe secret keys exposed
- ✅ No password hashes in responses
- ✅ No unnecessary PII in logs
Security Risk: CRITICAL - Key compromise
Objective: Verify file upload validation
Test Steps:
- Try to upload .exe file as logo
- Try to upload PHP file
- Upload very large file (> 10MB)
- Upload with malicious filename
Expected Results:
- ✅ Only images allowed for logos
- ✅ File type validation
- ✅ File size limits enforced
- ✅ Filename sanitized
- ✅ Files scanned for malware (if applicable)
Security Risk: HIGH - Malware distribution
Objective: Verify session cookies secure
Test Steps:
- Login and inspect cookies
- Check cookie attributes
- Try to steal session token
Expected Results:
- ✅ Cookies have HttpOnly flag
- ✅ Cookies have Secure flag (HTTPS)
- ✅ SameSite=Lax or Strict
- ✅ Appropriate expiration time
- ✅ Session invalidated on logout
Security Risk: CRITICAL - Session hijacking
Objective: Verify all API routes require auth
Test Steps:
- Call protected API without token
- Call with expired token
- Call with invalid token
- Call with token from different tenant
Expected Results:
- ✅ Returns 401 Unauthorized
- ✅ No data leaked in error
- ✅ Tenant validation works
- ✅ Role validation works
Security Risk: CRITICAL - Unauthorized access
Objective: Verify password requirements
Test Steps:
- Try to register with weak password "123"
- Try common password "password123"
- Check password hashing
Expected Results:
- ✅ Minimum length enforced (8+ chars)
- ✅ Complexity requirements (optional)
- ✅ Passwords hashed with bcrypt
- ✅ Never stored in plain text
Security Risk: HIGH - Account compromise
Objective: Verify HTTPS redirect
Test Steps:
- Visit http://school-a.localhost:3000
- Check redirect to HTTPS
Expected Results:
- ✅ Redirects to HTTPS (in production)
- ✅ HSTS header set
- ✅ Secure cookies only on HTTPS
Security Risk: HIGH - Man-in-the-middle attacks
| Category | Total Tests | Priority | Estimated Time | Dependencies |
|---|---|---|---|---|
| 1. Multi-Tenant Isolation | 8 | P0 | 4 hours | Test data, 2 schools |
| 2. Authentication | 6 | P0 | 3 hours | Email service |
| 3. Payment Flows | 7 | P0 | 5 hours | Stripe test mode |
| 4. Join School Flow | 5 | P1 | 2 hours | Multi-user setup |
| 5. Onboarding Wizard | 4 | P2 | 2 hours | New accounts |
| 6. Plan Limits | 4 | P2 | 2 hours | Test plans |
| 7. Revenue Dashboard | 3 | P2 | 1 hour | Transaction data |
| 8. Security Audit | 10 | P0 | 6 hours | Security tools |
| TOTAL | 47 | - | 25 hours | - |
# 1. Install Playwright
npm install -D @playwright/test
# 2. Install browsers
npx playwright install
# 3. Set up test database
supabase db reset --db-url test-- Create 2 test schools
INSERT INTO tenants (id, name, slug, status) VALUES
('test-school-a-id', 'Test School A', 'test-school-a', 'active'),
('test-school-b-id', 'Test School B', 'test-school-b', 'active');
-- Create test users
-- (handled by Playwright tests dynamically)
-- Create test courses
-- (handled by Playwright tests dynamically)
-- Create test products
-- (handled by Playwright tests dynamically)# .env.test
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY=test-key
SUPABASE_SERVICE_ROLE_KEY=test-service-key
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_test_...
NEXT_PUBLIC_PLATFORM_DOMAIN=localhost- Multi-Tenant Isolation (Tests 1.1-1.8)
- Authentication (Tests 2.1-2.6)
- Security Audit (Tests 8.1-8.10)
Blockers: If ANY test fails, do not proceed
- Payment Flows (Tests 3.1-3.7)
Blockers: Critical for revenue model
- Join School Flow (Tests 4.1-4.5)
- Onboarding Wizard (Tests 5.1-5.4)
- Plan Limits (Tests 6.1-6.4)
- Revenue Dashboard (Tests 7.1-7.3)
Blockers: Fix before production launch
- ❌ Any cross-tenant data leak
- ❌ Authentication bypass
- ❌ Payment fraud vulnerability
- ❌ SQL injection success
- ❌ XSS execution
- ❌ Session hijacking possible
⚠️ Role-based access control bypass⚠️ Revenue calculation errors⚠️ Enrollment isolation issues⚠️ Rate limiting not working
- 💛 Join school flow errors
- 💛 Onboarding wizard bugs
- 💛 Plan limit bypass
- 💛 Dashboard display errors
- Review and approve this plan
- Set up Playwright test environment
- Write test scripts using Playwright MCP
- Execute Phase 1 tests (Critical Security)
- Execute Phase 2 tests (Payment Security)
- Execute Phase 3 tests (User Experience)
- Generate test report
- Create security audit checklist
- Fix all critical and high-priority issues
- Re-test and verify fixes
Status: 📋 Plan Complete - Ready for Execution Next Action: Begin writing Playwright tests for Category 1 (Multi-Tenant Isolation)