> ## Documentation Index
> Fetch the complete documentation index at: https://docs-terra.withunify.org/llms.txt
> Use this file to discover all available pages before exploring further.

# System Map

> Visual overview of Terra's architecture and component relationships

# System Map

> A bird's-eye view of how Terra's components connect.

This page provides visual maps of Terra's architecture. Use it as a reference when navigating the codebase or debugging data flow issues.

***

## High-Level Architecture

Terra follows a layered architecture with clear boundaries between concerns:

```mermaid theme={null}
flowchart TB
    subgraph Clients["Client Layer"]
        Admin[Admin Dashboard]
        Portal[Applicant Portal]
        Public[Public Forms]
    end

    subgraph Edge["Edge Layer"]
        MW[Middleware]
        CDN[Vercel Edge]
    end

    subgraph App["Application Layer"]
        RSC[React Server Components]
        SA[Server Actions]
        API[API Routes]
    end

    subgraph Services["Service Layer"]
        Auth[Auth Service]
        Forms[Forms Engine]
        Files[File Service]
        Queue[Async Queue]
        Notify[Notification Service]
    end

    subgraph External["External Services"]
        WorkOS[WorkOS]
        Supabase[(Supabase)]
        Storage[(Private Storage)]
        Airtable[Airtable]
        Resend[Resend]
        Twilio[Twilio]
        Drive[Google Drive]
    end

    Clients --> Edge
    Edge --> App
    App --> Services
    Services --> External
```

***

## Request Flow

Every request follows a consistent path through the system:

```mermaid theme={null}
sequenceDiagram
    participant C as Client
    participant M as Middleware
    participant R as RSC/Route
    participant S as Server Action
    participant D as Supabase
    participant E as External APIs

    C->>M: Request
    M->>M: Check auth cookie
    M->>M: Resolve custom domain
    M->>R: Forward (with context)
    R->>S: Call server action
    S->>S: Validate permissions
    S->>D: Query database
    D-->>S: Data
    S->>E: (Optional) External call
    E-->>S: Response
    S-->>R: Result
    R-->>C: Rendered page
```

### Key Decision Points

| Step          | Decision        | Fail Behavior            |
| ------------- | --------------- | ------------------------ |
| Middleware    | Valid session?  | Redirect to login        |
| Middleware    | Custom domain?  | Route to correct folder  |
| Server Action | Has permission? | Throw unauthorized       |
| Database      | RLS policies    | N/A (using service role) |

***

## Form Submission Flow

When an applicant submits a form, here's what happens:

```mermaid theme={null}
flowchart TD
    subgraph Submit["1. Submission"]
        A[Applicant clicks Submit]
        V[Client validation]
        S[Server action]
        DB[(Save to database)]
    end

    subgraph Async["2. Async Processing"]
        Q[(Async Queue)]
        P[Queue Processor]
    end

    subgraph Integrations["3. Integrations"]
        AT[Airtable Sync]
        EM[Email Receipt]
        WH[Webhooks]
    end

    A --> V
    V --> S
    S --> DB
    DB --> Q

    P --> Q
    Q --> AT
    Q --> EM
    Q --> WH

    AT -.->|retry on fail| Q
    EM -.->|retry on fail| Q
    WH -.->|retry on fail| Q
```

### Timing

| Step                  | Typical Duration  | Blocking? |
| --------------------- | ----------------- | --------- |
| Client validation     | 50-100ms          | Yes       |
| Server save           | 100-200ms         | Yes       |
| Queue enqueue         | 10-20ms           | Yes       |
| **User sees success** | **\~300ms total** | —         |
| Airtable sync         | 500ms-2s          | No        |
| Email send            | 200-500ms         | No        |
| Webhook fire          | 100-500ms         | No        |

The applicant sees "Thank you" in \~300ms. Everything else happens in the background.

***

## Authentication Flow

How users authenticate and how sessions are managed:

```mermaid theme={null}
sequenceDiagram
    participant U as User
    participant T as Terra
    participant W as WorkOS

    U->>T: Visit /auth/login
    T->>W: Redirect to AuthKit
    W->>W: User authenticates
    W->>T: Callback with code
    T->>W: Exchange code for session
    W-->>T: Session + user data
    T->>T: Create encrypted cookie
    T->>T: Sync to user_profiles table
    T->>U: Redirect to dashboard
```

### Session Management

```mermaid theme={null}
flowchart LR
    subgraph Cookie["Encrypted Cookie (7 days)"]
        UID[User ID]
        Email[Email]
        Role[Role]
        Exp[Expiry]
    end

    subgraph Middleware["On Every Request"]
        Decrypt[Decrypt cookie]
        Check[Check expiry]
        Attach[Attach to request]
    end

    Cookie --> Decrypt
    Decrypt --> Check
    Check -->|valid| Attach
    Check -->|expired| Login[Redirect to login]
```

***

## Data Model Overview

The core database entities and their relationships:

```mermaid theme={null}
erDiagram
    ORGANIZATION ||--o{ FOLDER : contains
    ORGANIZATION ||--o{ USER_PROFILE : has
    FOLDER ||--o{ FORM : contains
    FOLDER ||--o{ FOLDER_MEMBER : has
    FORM ||--o{ FORM_VERSION : versions
    FORM ||--o{ SUBMISSION : receives
    SUBMISSION ||--o{ ASYNC_OPERATION : triggers
    USER_PROFILE ||--o{ SUBMISSION : creates
    APPLICANT ||--o{ SUBMISSION : owns

    ORGANIZATION {
        uuid id PK
        string name
        jsonb branding
        jsonb localization
    }

    FOLDER {
        uuid id PK
        string name
        string slug
        string custom_domain
    }

    FORM {
        uuid id PK
        string slug
        string status
        jsonb published_schema
        jsonb draft_schema
    }

    SUBMISSION {
        uuid id PK
        string reference_id
        string status
        jsonb answers
        timestamp submitted_at
    }
```

For complete schema documentation, see [Database Schema](/core-systems/data/database-schema).

***

## File Upload Flow

How files move from the applicant's browser to secure storage:

```mermaid theme={null}
sequenceDiagram
    participant B as Browser
    participant S as Server Action
    participant SB as Supabase Storage
    participant GD as Google Drive

    B->>S: Request signed upload URL
    S->>S: Validate form + auth
    S->>SB: createSignedUploadUrl()
    SB-->>S: Signed URL (5 min expiry)
    S-->>B: Return signed URL

    alt Supabase Storage
        B->>SB: Upload file directly
        SB-->>B: Success
    else Google Drive (if configured)
        B->>S: Upload via API route
        S->>GD: Stream to Drive folder
        GD-->>S: File ID
        S-->>B: Success
    end
```

### Storage Paths

Files are stored with unpredictable paths to prevent enumeration:

```
form-uploads/
  {formId}/
    {uuid}/
      {sanitized-filename}
```

***

## Async Queue Architecture

The persistent queue that powers background processing:

```mermaid theme={null}
flowchart TD
    subgraph Producers["Producers"]
        Submit[Form Submission]
        StatusChange[Status Change]
        Sync[Manual Sync]
    end

    subgraph Queue["async_operations Table"]
        Pending[(Pending)]
        Processing[(Processing)]
        Completed[(Completed)]
        Failed[(Failed)]
        DeadLetter[(Dead Letter)]
    end

    subgraph Consumers["Queue Processor"]
        Pick[Pick oldest pending]
        Process[Execute operation]
        Result{Success?}
    end

    Submit --> Pending
    StatusChange --> Pending
    Sync --> Pending

    Pick --> Pending
    Processing --> Process
    Process --> Result
    Result -->|yes| Completed
    Result -->|no, retries left| Pending
    Result -->|no, max retries| DeadLetter
```

### Operation Types

| Type               | Trigger                  | Retry Strategy                 |
| ------------------ | ------------------------ | ------------------------------ |
| `airtable_sync`    | Submission/update        | 5 retries, exponential backoff |
| `send_email`       | Submission               | 3 retries, 1 min delay         |
| `send_sms`         | Submission/status change | 3 retries, 1 min delay         |
| `fire_webhook`     | Submission/status change | 5 retries, exponential backoff |
| `plaid_enrichment` | Plaid link complete      | 3 retries, 30s delay           |

***

## Directory Structure

Where to find things in the codebase:

```
apps/terra/src/
├── app/                    # Next.js App Router
│   ├── (dashboard)/        # Admin routes (protected)
│   ├── (portal)/           # Applicant portal routes
│   ├── (public)/           # Public routes
│   ├── actions/            # Server actions (25 files)
│   ├── api/                # API routes (webhooks, uploads)
│   ├── auth/               # Auth callback routes
│   ├── f/[slug]/           # Public form renderer
│   └── p/[slug]/           # Portal program page
│
├── components/             # React components
│   ├── engine/             # Form field renderers
│   ├── form-builder/       # Visual editor
│   ├── dashboard/          # Admin UI
│   ├── portal/             # Applicant UI
│   └── emails/             # React Email templates
│
├── lib/                    # Business logic
│   ├── auth.ts             # Session management
│   ├── supabase.ts         # Database clients
│   ├── security.ts         # Security utilities
│   ├── async-queue.ts      # Queue operations
│   ├── logic-engine.ts     # Form visibility rules
│   └── form-import/        # AI import pipeline
│
├── stores/                 # Zustand stores
│   └── form-builder-store.ts
│
├── types/                  # TypeScript types
│   └── schema.ts           # Form schema (478 lines)
│
└── middleware.ts           # Edge middleware
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Design Philosophy" icon="lightbulb" href="/foundation/design-philosophy">
    Why we made these architectural choices
  </Card>

  <Card title="Database Schema" icon="database" href="/core-systems/data/database-schema">
    Complete table documentation
  </Card>
</CardGroup>
