# QA Checklist — Pre-Launch E2E Testing
# 2026-02-26

## Core Flow: Contractor Signup → Job Post → Match → Hire → Rate

### 1. Contractor Signup (`/auth/signup` or `/contractor/signup`)
- [ ] Sign up with email + password + AU phone
- [ ] User type selector (contractor) works
- [ ] Terms checkbox required
- [ ] Redirects to contractor onboarding
- [ ] ABN lookup + AI company research works
- [ ] Company review step shows correct data
- [ ] Profile created with `onboarding_completed: true`
- [ ] Dashboard loads with welcome card + profile checklist
- [ ] Edge: duplicate email shows "already registered" message
- [ ] Edge: invalid ABN shows validation error
- [ ] Edge: browser refresh mid-signup (progress lost — known F6)

### 2. Job Posting (`/contractor/post-job`)
- [ ] Manual entry: trade select → details → location → rate → review
- [ ] Voice-to-job: record → AI generates job → review
- [ ] AI pre-fills job title and description
- [ ] Location autocomplete works
- [ ] Job saved to DB with status "active"
- [ ] Match finding triggers automatically
- [ ] Edge: very short voice recording
- [ ] Edge: empty required fields blocked
- [ ] Edge: posting while session expired → auth redirect

### 3. Worker Signup (`/worker/signup`)
- [ ] Sign up with email + password + phone (AU or international)
- [ ] Method selection: type vs voice
- [ ] Voice pathway: record → AI extracts trades/experience/location
- [ ] Manual pathway: trade → experience → location → availability → certs → phone → review
- [ ] Profile saved with worker_profiles record
- [ ] Dashboard loads with welcome card
- [ ] Edge: international phone number (+44, +353) accepted ✅
- [ ] Edge: no trade selected → blocked from continuing
- [ ] Edge: browser refresh loses progress (known F6)

### 4. Job Application (`/worker/jobs`)
- [ ] Job list loads with active jobs
- [ ] Trade filter works
- [ ] Swipe right to apply
- [ ] Profile completeness gate (name, phone, trade, experience required)
- [ ] Match created with status "applied"
- [ ] Contractor gets notification + SMS
- [ ] Edge: apply to same job twice → "Already applied" error
- [ ] Edge: apply to own job (if somehow both types) → blocked
- [ ] Edge: apply to closed job → "No longer active"

### 5. Match Review + Hire (`/contractor/matches`)
- [ ] Matches list shows applied workers
- [ ] Worker profile details visible
- [ ] Accept → Stripe checkout opens
- [ ] $50 AUD charge via Stripe Checkout
- [ ] On success: redirect to payment-success page
- [ ] Match updated to "hired" + payment to "charged"
- [ ] Worker gets hire notification + SMS + email
- [ ] Conversation auto-created between contractor and worker
- [ ] Reject → match status "rejected" + gentle notification to worker
- [ ] Edge: pay then browser crash → webhook catches up
- [ ] Edge: double-click pay → duplicate charge protection ✅
- [ ] Edge: Stripe card declined → stays on checkout, no DB corruption

### 6. Rating (`/rate/[matchId]`)
- [ ] Only hired matches show rating prompt on dashboard
- [ ] 1-5 star rating works
- [ ] Written review optional
- [ ] Rating saved to DB
- [ ] Edge: submit twice → "Already rated" check
- [ ] Edge: rate non-hired match → blocked

### 7. Messaging (`/messages`)
- [ ] Conversation auto-created on hire
- [ ] Send/receive messages works
- [ ] Real-time updates
- [ ] Edge: message to non-existent conversation → error

### 8. No-Show Flow (`/contractor/hired/[matchId]`)
- [ ] Report button visible after 48h grace period
- [ ] Before grace period → shows time remaining
- [ ] After grace → flags match, notifies worker
- [ ] Refund available via admin `/api/payments/refund`

---

## Payment Edge Cases (Stripe)

### Verified ✅
- [x] Live API key configured
- [x] Webhook endpoint enabled (payment_intent.succeeded)
- [x] Product + price ($50 AUD) active
- [x] Checkout session creation works
- [x] Duplicate charge prevention (match_id check)
- [x] ABN on checkout page (custom_text)
- [x] Receipt email sent to contractor
- [x] Idempotency keys on checkout creation
- [x] Refund API endpoint ready

### Needs Testing
- [ ] Card declined → user stays on Stripe page, no DB side effects
- [ ] Payment succeeds but webhook delayed → confirm-hire fallback handles it
- [ ] Payment succeeds but confirm-hire fails → webhook catches up
- [ ] Network timeout during checkout creation → rate limit prevents rapid retry
- [ ] Refund for no-show → Stripe refund created, DB updated, email sent
- [ ] Partial refund (not implemented — full refund only for now)

### Security Issues Found & Fixed
| Issue | Severity | Status |
|-------|----------|--------|
| `/api/match/reject` — no CSRF protection | Medium | 🔧 FIXING |
| `/api/payments/confirm-hire` — no CSRF | Medium | 🔧 FIXING |
| `/api/payments/confirm-hire` — no rate limiting | Medium | 🔧 FIXING |
| `/api/feedback` POST — no CSRF | Low | 🔧 FIXING |
| `/api/feedback` POST — no rate limiting | Low | 🔧 FIXING |

---

## Known Issues (Non-Blocking)
1. F2: ABN required at contractor signup (should be optional)
2. F5: Worker signup is 10 steps (target: 7)
3. F6: No progress persistence in signup flows
4. Webhook missing `checkout.session.completed` event (confirm-hire handles it)

*QA Checklist by Builder 🔨 — 2026-02-26*
