# API Client & Authentication

# API Client & Authentication

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [.githooks/pre-commit](.githooks/pre-commit)
- [package.json](package.json)
- [scripts/version-sync.mjs](scripts/version-sync.mjs)
- [src/app.d.ts](src/app.d.ts)
- [src/lib/api.ts](src/lib/api.ts)
- [src/lib/auth/redirect-cache.ts](src/lib/auth/redirect-cache.ts)
- [src/lib/backend-availability.ts](src/lib/backend-availability.ts)
- [src/lib/version.ts](src/lib/version.ts)
- [src/routes/login/+page.svelte](src/routes/login/+page.svelte)
- [vite.config.ts](vite.config.ts)

</details>



This section provides a deep dive into the communication layer between the Primebrick frontend and the backend services. It covers the request pipeline, session management, and the authentication flow implemented via SvelteKit and the central API utility.

## The `apiFetch` Pipeline

The `apiFetch` function is the primary entry point for all network requests. It wraps the native `fetch` API to provide features like SSR URL rewriting, automatic token refresh, and gateway failure attribution.

### Implementation Details
The pipeline follows a specific sequence of operations for every request:

1.  **SSR URL Rewriting**: If executed on the server during Server-Side Rendering (SSR), relative `/api/` paths are rewritten to absolute URLs using the `PUBLIC_API_ORIGIN` environment variable [src/lib/api.ts:142-145]().
2.  **Health Check**: In the browser, it calls `ensureBackendOnlineOrThrow()` to prevent requests if the backend is known to be unreachable [src/lib/api.ts:148-150]().
3.  **Cache Control**: Requests to the entity API (`/api/v1/entities`) default to `cache: 'no-store'` to prevent stale data [src/lib/api.ts:154-156]().
4.  **Credential Handling**: `credentials: 'include'` is enforced to ensure HttpOnly cookies are sent with every request [src/lib/api.ts:153-153]().
5.  **Failure Attribution**: Network errors (e.g., DNS failure, timeout) trigger `noteGatewayFailure(503)`, which updates the global health state [src/lib/api.ts:166-168]().

### Token Refresh & 401 Recovery
The client implements a transparent 401 recovery mechanism. When a request returns a `401 Unauthorized` status:
-   It checks if a local session exists in `sessionStorage` [src/lib/api.ts:186-194]().
-   If the token is expired (or about to expire within 30 seconds), it triggers a `refreshAccessToken()` call to `/api/v1/auth/refresh` [src/lib/api.ts:197-200]().
-   **Concurrency Control**: Multiple simultaneous 401s are queued behind a single `refreshPromise` to avoid redundant refresh calls [src/lib/api.ts:99-106]().
-   Upon success, the original request is retried [src/lib/api.ts:202-202]().

### Request Pipeline Flow
The following diagram illustrates the lifecycle of an API request through `apiFetch`.

**API Request Lifecycle**
```mermaid
sequenceDiagram
    participant App as "Code Entity: UI Component"
    participant AF as "Function: apiFetch"
    participant BE as "Backend: API Origin"
    participant HS as "Store: backendState"

    App->>AF: call apiFetch("/api/v1/...")
    AF->>AF: check environment (SSR vs Browser)
    alt is Browser
        AF->>HS: ensureBackendOnlineOrThrow()
    end
    AF->>BE: fetch(url, init)
    
    alt Network Error
        AF->>HS: noteGatewayFailure(503)
        AF-->>App: throw ApiUnreachableError
    else 401 Unauthorized
        AF->>AF: triggerRefresh()
        AF->>BE: POST /api/v1/auth/refresh
        alt Refresh Success
            AF->>BE: retry original request
            BE-->>AF: 200 OK
            AF-->>App: Response
        else Refresh Fail
            AF->>AF: saveRedirectUrl()
            AF->>AF: window.location.href = "/login"
        end
    else 503 Service Unavailable
        AF-->>App: throw ApiDatabaseUnavailableError
    end
```
Sources: `src/lib/api.ts`, `src/lib/backend-availability.ts`, `src/lib/auth/redirect-cache.ts`

---

## Authentication Flow

The authentication system is centered around a SPA-mode login page that interacts with the `/api/v1/auth/login` endpoint.

### Login Page Implementation
The login flow uses `sveltekit-superforms` in SPA mode to manage form state and validation without full-page reloads.

-   **Validation**: Uses a Zod schema (`loginSchema`) to validate `username` and `password` on the client side [src/routes/login/+page.svelte:34-37]().
-   **Submission**: The `onUpdate` hook intercepts the form submission to perform the asynchronous `apiFetch` to the login endpoint [src/routes/login/+page.svelte:51-63]().
-   **Error Mapping**: Backend errors (RFC 7807) are mapped to UI-friendly messages. 401 errors are specifically translated using the `mapRFC7807ToMessageKey` utility [src/routes/login/+page.svelte:76-90]().
-   **Session Storage**: On successful login, the user profile is stored in the `userProfileStore` (which persists to `sessionStorage`) [src/routes/login/+page.svelte:118-121]().

### Redirect Cache
Before redirecting an unauthenticated user to `/login`, the application saves the intended destination using `saveRedirectUrl`.
-   **Storage**: Uses `sessionStorage` under the key `redirectAfterLogin` [src/lib/auth/redirect-cache.ts:6-12]().
-   **Recovery**: After a successful login, `getAndClearRedirectUrl` is called to navigate the user back to their original target [src/routes/login/+page.svelte:123-124]().

### Authentication Data Flow
This diagram maps the authentication process to the specific code entities involved.

**Login and Session Management**
```mermaid
graph TD
    subgraph UI ["Route: /login"]
        LF["Component: LoginForm (superForm)"]
        ZS["Schema: loginSchema (Zod)"]
    end

    subgraph Logic ["Lib: API & Auth"]
        AF["Function: apiFetch"]
        RC["Module: redirect-cache.ts"]
        UPS["Store: userProfileStore"]
    end

    subgraph Storage ["Browser Storage"]
        SS["sessionStorage ('user')"]
        RS["sessionStorage ('redirectAfterLogin')"]
    end

    LF -->|Validate| ZS
    LF -->|POST /login| AF
    AF -->|Set User| UPS
    UPS -->|Sync| SS
    LF -->|Read Target| RC
    RC -->|Get/Clear| RS
    LF -->|Redirect| Window["window.location.href"]
```
Sources: `src/routes/login/+page.svelte`, `src/lib/user-profile-store.svelte`, `src/lib/auth/redirect-cache.ts`

---

## Health & Module Discovery

The API client also provides specialized functions for monitoring system health and discovering available backend modules.

### Health Probing
-   **`fetchHealth`**: Performs a GET request to `/health`. It is used by the `probeHealth()` loop to update the global `backendState` [src/lib/api.ts:223-231]().
-   **Validation**: The response is expected to match the `HealthPayload` interface, containing status information for the backend, database, and identity provider (IdP) [src/lib/api-types.ts:8]().

### Module Discovery
-   **`fetchModules`**: Retrieves a list of installed backend modules from `/api/v1/modules` [src/lib/api.ts:233-237]().
-   **Usage**: This data is used to populate the navigation shell and settings pages with dynamic module information.

| Function | Endpoint | Purpose |
| :--- | :--- | :--- |
| `apiFetch` | Variable | General purpose authenticated requests with auto-refresh. |
| `fetchHealth` | `/health` | System status monitoring (DB, IdP, BE). |
| `fetchModules` | `/api/v1/modules` | Discovery of backend extensions and features. |
| `apiFetchWithTimeout` | Variable | Requests with a forced `AbortController` signal [src/lib/api.ts:213-221](). |

Sources: `src/lib/api.ts`, `src/lib/api-types.ts`

---
