44:  onboarding_completed boolean DEFAULT false,
227:CREATE POLICY "Public profiles are viewable by everyone"
231:CREATE POLICY "Users can update their own profile"
235:CREATE POLICY "Users can insert their own profile"
240:CREATE POLICY "Companies are viewable by everyone"
244:CREATE POLICY "Contractors can insert their own company"
248:CREATE POLICY "Contractors can update their own company"
253:CREATE POLICY "Worker profiles are viewable by everyone"
257:CREATE POLICY "Workers can insert their own profile"
261:CREATE POLICY "Workers can update their own profile"
266:CREATE POLICY "Jobs are viewable by everyone"
270:CREATE POLICY "Contractors can insert jobs for their company"
278:CREATE POLICY "Contractors can update their own jobs"
287:CREATE POLICY "Users can view their own matches"
298:CREATE POLICY "System can insert matches"
302:CREATE POLICY "Involved parties can update matches"
314:CREATE POLICY "Ratings are viewable by everyone"
318:CREATE POLICY "Match participants can insert ratings"
323:CREATE POLICY "Company owners can view their payments"
331:CREATE POLICY "System can insert payments"
336:CREATE POLICY "Users can view their own notifications"
340:CREATE POLICY "System can insert notifications"
344:CREATE POLICY "Users can update their own notifications"


Bash

grep -n "profiles" /home/ccuser/the-50-dollar-app/supabase/schema.sql | head -20


34:CREATE TABLE profiles (
50:CREATE TRIGGER profiles_updated_at
51:  BEFORE UPDATE ON profiles
57:  profile_id uuid NOT NULL UNIQUE REFERENCES profiles ON DELETE CASCADE,
74:-- Worker profiles (worker-specific)
75:CREATE TABLE worker_profiles (
77:  profile_id uuid NOT NULL UNIQUE REFERENCES profiles ON DELETE CASCADE,
92:CREATE TRIGGER worker_profiles_updated_at
93:  BEFORE UPDATE ON worker_profiles
127:  worker_id uuid NOT NULL REFERENCES profiles ON DELETE CASCADE,
148:  from_id uuid NOT NULL REFERENCES profiles ON DELETE CASCADE,
149:  to_id uuid NOT NULL REFERENCES profiles ON DELETE CASCADE,
170:  profile_id uuid NOT NULL REFERENCES profiles ON DELETE CASCADE,
183:CREATE INDEX idx_profiles_type ON profiles (type);
184:CREATE INDEX idx_profiles_suburb ON profiles (suburb);
189:CREATE INDEX idx_worker_profiles_profile_id ON worker_profiles (profile_id);
190:CREATE INDEX idx_worker_profiles_trades ON worker_profiles USING gin (trades);
191:CREATE INDEX idx_worker_profiles_availability ON worker_profiles (availability);
192:CREATE INDEX idx_worker_profiles_certifications ON worker_profiles USING gin (certifications);
217:ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;


Perfect! Now let me create a comprehensive summary document. Let me compile all the findings:

## Summary of Findings

Based on my thorough search of the `/home/ccuser/the-50-dollar-app` codebase, here are all the findings for your seven search items:

---

### 1. **References to "onboarding_completed" — How it's checked and set**

**Files with onboarding_completed references:**

- `/home/ccuser/the-50-dollar-app/supabase/schema.sql` (Line 44)
  - Column definition: `onboarding_completed boolean DEFAULT false`
  - Part of the `profiles` table

- `/home/ccuser/the-50-dollar-app/src/lib/types.ts` (Line 38)
  - TypeScript interface property: `onboarding_completed: boolean`

- `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/worker/profile/build/page.tsx` (Lines 336-341)
  - **SET** operation: When user saves their profile after completing the build flow
  ```typescript
  await supabase.from("profiles").update({
    suburb: location,
    onboarding_completed: true,
  }).eq("id", user.id);
  ```

- `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/contractor/signup/page.tsx` (Lines 255-258)
  - **SET** operation: When contractor confirms their company profile
  ```typescript
  await supabase.from("profiles").update({
    name: companyData.name,
    onboarding_completed: true,
  }).eq("id", user.id);
  ```

- `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/worker/signup/page.tsx` (Lines 214-218)
  - **SET** operation: When worker completes initial signup
  ```typescript
  const profileResult = await supabase.from("profiles").update({
    name: user.email?.split("@")[0] ?? "",
    suburb,
    onboarding_completed: true,
  }).eq("id", user.id);
  ```

- `/home/ccuser/the-50-dollar-app/src/app/api/match/find-matches/route.ts` (Lines 70-71)
  - **CHECKED** operation: When finding workers for matching, the API filters for workers with completed onboarding
  ```typescript
  const { data: workers, error: workersError } = await admin
    .from("worker_profiles")
    .select("*, profiles!inner(id, suburb, location, onboarding_completed)")
    .eq("profiles.onboarding_completed", true);
  ```

---

### 2. **References to "Edit Profile" or "edit profile" or "Build Profile"**

**File:** `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/dashboard/page.tsx`

- Line 193: `<Link href="/contractor/signup">Edit Profile</Link>` (for contractors)
- Line 231: `<Link href="/worker/profile/build">Edit Profile</Link>` (for workers)

These are buttons in the dashboard that direct users to edit their profiles.

---

### 3. **Worker profile page at src/app/(authenticated)/worker/profile/page.tsx**

**File:** `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/worker/profile/page.tsx` (6 lines total)

This is a simple redirect page:
```typescript
"use client";

import { redirect } from "next/navigation";

export default function WorkerProfilePage() {
  redirect("/worker/profile/build");
}
```

**What it does:** It's a simple wrapper that immediately redirects users from `/worker/profile` to `/worker/profile/build`. This is the actual profile editing page.

---

### 4. **Redirect logic that sends users to the profile build page**

**Primary redirect:** `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/worker/profile/page.tsx` (Lines 1-5)
- Redirects `/worker/profile` → `/worker/profile/build`

**Dashboard links:**
- `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/dashboard/page.tsx`
  - Line 231 (workers): Links to `/worker/profile/build`
  - Line 193 (contractors): Links to `/contractor/signup`

**Middleware routing:**
- `/home/ccuser/the-50-dollar-app/src/lib/supabase/middleware.ts` (Lines 38-76)
  - Middleware determines if user is verified and redirects accordingly
  - Does NOT explicitly check `onboarding_completed`, but protects certain routes
  - If not email-verified: redirects to `/auth/verify-email`
  - If verified on auth pages: redirects to `/dashboard`

---

### 5. **How the dashboard decides what to show for workers vs contractors**

**File:** `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/dashboard/page.tsx`

**Decision logic (Line 28):**
```typescript
const isContractor = profile?.type === "contractor";
```

**What's shown based on type:**

**For Contractors (isContractor = true):**
- Active Jobs count card (Lines 127-133)
- New Matches count card (Lines 134-139)
- "Post a Job" CTA (Lines 143-158)
- "View Matches" button if matches exist (Lines 161-178)
- "Company Profile" with edit link to `/contractor/signup` (Lines 181-196)

**For Workers (isContractor = false):**
- "Find Work" CTA linking to `/worker/jobs` (Lines 201-216)
- "Your Profile" card with edit link to `/worker/profile/build` (Lines 219-234)

Both receive the pending ratings prompt if applicable (Lines 100-122).

---

### 6. **Supabase storage bucket configured for avatars/profile pictures**

**FINDING:** No Supabase storage bucket for avatars is explicitly configured in the codebase.

However, the `avatar_url` column exists and is referenced:
- `/home/ccuser/the-50-dollar-app/supabase/schema.sql` (Line 40): `avatar_url text`
- Used in messaging/conversations to display user avatars
- Files referencing avatar_url:
  - `/home/ccuser/the-50-dollar-app/src/app/api/messages/[id]/route.ts`
  - `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/messages/page.tsx`
  - `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/messages/[conversationId]/page.tsx`
  - `/home/ccuser/the-50-dollar-app/src/app/(authenticated)/contractor/matches/page.tsx`
  - `/home/ccuser/the-50-dollar-app/src/components/ConversationPreview.tsx`

The storage bucket appears to be **NOT yet implemented** — only the URL column exists. The actual file storage infrastructure would need to be set up separately (likely using Supabase Storage or a third-party service).

---

### 7. **Avatar_url column in profiles table (migrations)**

**Schema definition:** `/home/ccuser/the-50-dollar-app/supabase/schema.sql` (Line 40)
```sql
avatar_url text,
```

The profiles table definition includes:
- Column type: `text` (stores URL as string)
- No explicit default value
- Can be NULL

**Migrations reference avatar_url:**
- `/home/ccuser/the-50-dollar-app/supabase/migrations/20260208000002_fix_messaging_search_path.sql` (Line 21)
- `/home/ccuser/the-50-dollar-app/supabase/migrations/20260208000004_add_last_seen_at.sql` (Line 21)
- `/home/ccuser/the-50-dollar-app/supabase/add-messaging.sql` (Line 118)

These migrations use `avatar_url` in views that display conversation participants, pulling the avatar URL from the profiles table.

---

### Summary Table

| Item | Status | Location |
|------|--------|----------|
| onboarding_completed checks | Implemented | API route, signup pages, schema |
| onboarding_completed sets | Implemented | 3 locations (worker signup, contractor signup, profile build) |
| Edit Profile links | Implemented | Dashboard page (lines 193, 231) |
| Profile build page | Implemented | `/worker/profile/build/page.tsx` (full flow) |
| Profile page redirect | Implemented | `/worker/profile/page.tsx` → `/worker/profile/build` |
| Dashboard logic | Implemented | Checks `profile.type === "contractor"` |
| Storage bucket | NOT implemented | Only avatar_url column exists, no actual storage configured |
| avatar_url column | Exists | In profiles table, used in messaging views |