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

# Auth & Row Level Security

> Authentication flow and multi-tenant data isolation

# Authentication & RLS

## Authentication Flow

HostMetrics uses Supabase Auth with email/password authentication.

```mermaid theme={null}
sequenceDiagram
    participant User
    participant App as Next.js App
    participant Auth as Supabase Auth
    participant DB as PostgreSQL

    User->>App: Enter email + password
    App->>Auth: signInWithPassword()
    Auth-->>App: Session (access_token + refresh_token)
    App->>App: AuthProvider stores session
    App->>DB: Query with access_token
    DB->>DB: RLS checks auth.uid() = user_id
    DB-->>App: User's data only
```

### AuthProvider

`src/components/auth/AuthProvider.tsx` provides a React Context with:

| Property           | Type                  | Description                |
| ------------------ | --------------------- | -------------------------- |
| `user`             | `User \| null`        | Current authenticated user |
| `session`          | `Session \| null`     | JWT session                |
| `isLoading`        | `boolean`             | Auth state loading         |
| `signOut()`        | `() => Promise<void>` | Sign out and redirect      |
| `refreshSession()` | `() => Promise<void>` | Force refresh session      |

The provider listens to `supabase.auth.onAuthStateChange()` for real-time session updates across browser tabs.

### Protected Routes

* `(dashboard)/` layout group — Requires authenticated session
* `(auth)/` layout group — Public (login, signup, reset password)
* `/fleet/[slug]` — Public fleet pages (no auth)
* `/p/[token]` — Token-authenticated investor portal
* `/r/[token]` — Token-authenticated investor report

### API Route Authentication

Server-side API routes validate tokens manually:

```typescript theme={null}
// Pattern used in /api/turo/sync, /api/tolls/sync, etc.
const authHeader = request.headers.get("authorization");
const token = authHeader?.replace("Bearer ", "");
const { data: { user }, error } = await supabase.auth.getUser(token);
if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
```

## Row Level Security (RLS)

Every table has RLS enabled with policies ensuring users can only access their own data.

### The Pattern

```sql theme={null}
-- SELECT: Users see only their own rows
CREATE POLICY "select_own" ON table_name
    FOR SELECT USING (user_id = auth.uid());

-- INSERT: Users can only insert rows with their own user_id
CREATE POLICY "insert_own" ON table_name
    FOR INSERT WITH CHECK (user_id = auth.uid());

-- UPDATE: Users can only update their own rows
CREATE POLICY "update_own" ON table_name
    FOR UPDATE USING (user_id = auth.uid());

-- DELETE: Users can only delete their own rows
CREATE POLICY "delete_own" ON table_name
    FOR DELETE USING (user_id = auth.uid());
```

### Application-Level Enforcement

In addition to RLS, the application code always filters by `user_id`:

```typescript theme={null}
// src/lib/db/_client.ts
export async function getCurrentUserId(): Promise<string> {
    const { data: { user } } = await getClient().auth.getUser();
    if (!user) throw new Error("Not authenticated");
    return user.id;
}

// Used in every DB module:
const userId = await getCurrentUserId();
const { data } = await supabase
    .from("trips")
    .select("*")
    .eq("user_id", userId);
```

This double enforcement (RLS + application filtering) ensures data isolation even if one layer has a bug.
