> ## 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.

# Welcome to Hub

> Unified applicant view across all Unify applications

# Welcome to Hub

> Hub is the single source of truth for applicant identity. See the complete lifecycle of every person—programs they've applied to, benefits they've received, fraud flags, documents, and interactions across Terra, Pathfinder, Airtable, and beyond.

When staff need to understand an applicant's full picture, they currently check multiple systems: Terra for submissions, Airtable for case notes, Pathfinder for screener results, and maybe a spreadsheet for payment history. Hub consolidates everything into one view.

***

## What Hub Does

Hub is a **unified applicant view** with four core capabilities:

<CardGroup cols={2}>
  <Card title="Applicant Search" icon="magnifying-glass">
    Find anyone by name, email, phone, SSN, submission ID, or any other identifier. Cross-reference across all connected systems.
  </Card>

  <Card title="Lifecycle View" icon="timeline">
    See everything that's happened: applications submitted, documents uploaded, decisions made, benefits received, fraud flags, and case notes.
  </Card>

  <Card title="Cross-Reference" icon="diagram-project">
    Find connections: "Show me other applicants at this address" or "with this bank account" or "from this IP address."
  </Card>

  <Card title="Data Aggregation" icon="layer-group">
    Pull data from Terra, Pathfinder, Airtable, and external systems into a unified profile.
  </Card>
</CardGroup>

***

## Who Uses Hub

**Primary Users: Staff Across Systems**

| Role                | Use Case                                            |
| ------------------- | --------------------------------------------------- |
| **Case Manager**    | Look up applicant history before making decisions   |
| **Fraud Analyst**   | Cross-reference suspicious patterns across programs |
| **Program Manager** | Understand applicant journey across programs        |
| **Support Staff**   | Answer questions from applicants about their status |

***

## Applicant Lifecycle

Hub tracks the complete journey of every applicant:

```mermaid theme={null}
flowchart TB
    subgraph Discovery ["Discovery"]
        Pathfinder[Pathfinder Screener]
        Referral[Partner Referral]
    end

    subgraph Application ["Application"]
        Terra[Terra Submission]
        Docs[Document Upload]
    end

    subgraph Review ["Review"]
        Airtable[Airtable Review]
        Sentinel[Fraud Analysis]
    end

    subgraph Outcome ["Outcome"]
        Approved[Approved]
        Denied[Denied]
        Pending[Pending Info]
    end

    subgraph Benefits ["Benefits"]
        Payment[Payment Issued]
        Renewal[Renewal Due]
    end

    Pathfinder --> Terra
    Referral --> Terra
    Terra --> Docs
    Docs --> Airtable
    Docs --> Sentinel
    Airtable --> Approved
    Airtable --> Denied
    Airtable --> Pending
    Sentinel --> Airtable
    Approved --> Payment
    Payment --> Renewal
```

***

## Profile View

The Hub profile shows everything about an applicant:

### Identity

```typescript theme={null}
interface ApplicantIdentity {
  // Core identifiers
  id: string;
  displayName: string;
  email?: string;
  phone?: string;

  // Verified fields
  firstName: VerifiedField<string>;
  lastName: VerifiedField<string>;
  dateOfBirth: VerifiedField<string>;
  ssn: VerifiedField<string>; // Masked: ***-**-1234

  // Address history
  addresses: {
    address: string;
    type: 'current' | 'previous';
    verifiedAt?: string;
    source: string;
  }[];

  // Linked accounts
  linkedSystems: {
    system: 'terra' | 'pathfinder' | 'airtable';
    externalId: string;
    linkedAt: string;
  }[];
}
```

### Applications

| Program           | Status       | Submitted    | Decision     | Amount  |
| ----------------- | ------------ | ------------ | ------------ | ------- |
| ERA 2024          | Approved     | Jan 15, 2024 | Jan 22, 2024 | \$3,500 |
| SNAP              | Referred     | Jan 15, 2024 | -            | -       |
| Childcare Subsidy | Pending Docs | Feb 1, 2024  | -            | -       |
| ERA 2023          | Approved     | Dec 5, 2023  | Dec 15, 2023 | \$2,800 |

### Benefits Received

```typescript theme={null}
interface BenefitRecord {
  programId: string;
  programName: string;
  applicationId: string;
  amount: number;
  paymentDate: string;
  paymentMethod: 'ach' | 'check' | 'card';
  status: 'pending' | 'sent' | 'cleared' | 'returned';
}
```

| Date         | Program  | Amount  | Method | Status  |
| ------------ | -------- | ------- | ------ | ------- |
| Jan 25, 2024 | ERA 2024 | \$3,500 | ACH    | Cleared |
| Dec 20, 2023 | ERA 2023 | \$2,800 | Check  | Cleared |

### Documents

All documents ever submitted across all programs:

| Document           | Program  | Uploaded     | Verified     |
| ------------------ | -------- | ------------ | ------------ |
| Paystub - Dec 2023 | ERA 2024 | Jan 15, 2024 | Yes (OCR)    |
| Driver's License   | ERA 2024 | Jan 15, 2024 | Yes (Manual) |
| Lease Agreement    | ERA 2024 | Jan 16, 2024 | Yes (Manual) |
| Paystub - Nov 2023 | ERA 2023 | Dec 5, 2023  | Yes (OCR)    |

### Fraud Status

```typescript theme={null}
interface FraudStatus {
  overallRisk: 'none' | 'low' | 'medium' | 'high';
  flags: {
    programId: string;
    flagType: string;
    severity: string;
    status: 'active' | 'cleared' | 'expired';
    createdAt: string;
    clearedAt?: string;
    clearedBy?: string;
  }[];
  blocklisted: boolean;
  blocklistReason?: string;
}
```

### Timeline

Chronological view of all events:

```
┌─────────────────────────────────────────────────────────────────┐
│  Timeline                                                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  Feb 1, 2024                                                   │
│  ├── 10:30am  Applied to Childcare Subsidy                     │
│  └── 10:32am  Uploaded: Proof of enrollment                    │
│                                                                 │
│  Jan 25, 2024                                                  │
│  └── 2:15pm   Payment issued: ERA 2024 - $3,500 (ACH)         │
│                                                                 │
│  Jan 22, 2024                                                  │
│  └── 4:45pm   Application approved: ERA 2024                   │
│                                                                 │
│  Jan 18, 2024                                                  │
│  └── 11:20am  Fraud review cleared: ERA 2024                   │
│               Note: "Address verified via utility bill"         │
│                                                                 │
│  Jan 17, 2024                                                  │
│  └── 9:00am   Fraud flag: ERA 2024 - Address mismatch          │
│               Auto-flagged by Sentinel                          │
│                                                                 │
│  Jan 16, 2024                                                  │
│  ├── 3:30pm   Uploaded: Lease agreement                        │
│  └── 3:35pm   Document verified (manual)                       │
│                                                                 │
│  Jan 15, 2024                                                  │
│  ├── 2:00pm   Applied to ERA 2024                              │
│  ├── 2:05pm   Uploaded: Paystub - Dec 2023                     │
│  ├── 2:06pm   Uploaded: Driver's license                       │
│  ├── 2:10pm   Referred to SNAP (Pathfinder match)              │
│  └── 2:15pm   Completed Pathfinder screener                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

***

## Cross-Reference Queries

Hub enables powerful cross-reference queries:

### By Address

"Show me all applicants at 123 Main St"

```sql theme={null}
SELECT DISTINCT a.*
FROM applicants a
JOIN applicant_addresses aa ON a.id = aa.applicant_id
WHERE aa.address_normalized = '123 MAIN ST APT 4 SEATTLE WA 98101';
```

### By Bank Account

"Show me all applicants with this bank account"

```sql theme={null}
SELECT DISTINCT a.*
FROM applicants a
JOIN submissions s ON a.id = s.applicant_id
WHERE s.data->>'bank_account_hash' = 'abc123...';
```

### By IP Address

"Show me all applications from this IP"

```sql theme={null}
SELECT s.*, a.display_name
FROM submissions s
JOIN applicants a ON s.applicant_id = a.id
WHERE s.metadata->>'ip_address' = '192.168.1.1'
ORDER BY s.created_at DESC;
```

### By Household

"Show me all members of this household"

```sql theme={null}
SELECT a.*
FROM applicants a
WHERE a.household_id = 'household-123'
ORDER BY a.relationship_to_head;
```

***

## Data Aggregation

Hub pulls data from multiple sources:

```mermaid theme={null}
flowchart LR
    subgraph Sources
        Terra[(Terra)]
        Pathfinder[(Pathfinder)]
        Airtable[(Airtable)]
        Sentinel[(Sentinel)]
    end

    subgraph Hub
        Aggregator[Data Aggregator]
        Profile[Unified Profile]
    end

    Terra -->|Submissions, Docs| Aggregator
    Pathfinder -->|Screener, Matches| Aggregator
    Airtable -->|Decisions, Notes| Aggregator
    Sentinel -->|Fraud Flags| Aggregator

    Aggregator --> Profile
```

### Source Priority

When data conflicts between sources, Hub uses priority rules:

| Field              | Priority Order                                   |
| ------------------ | ------------------------------------------------ |
| Name               | Admin-verified > OCR-verified > Self-reported    |
| Address            | Most recent verified > Most recent self-reported |
| Income             | Most recent verified > Average of reported       |
| SSN                | Any verified source                              |
| Application Status | Source system of record                          |

***

## Data Model

### Core Tables

```sql theme={null}
-- Unified applicant profile (extends @unify/identity)
CREATE TABLE hub_profiles (
  id UUID PRIMARY KEY,
  applicant_id UUID REFERENCES applicants,

  -- Aggregated data
  total_applications INTEGER DEFAULT 0,
  total_approved INTEGER DEFAULT 0,
  total_benefits_received BIGINT DEFAULT 0, -- cents
  first_application_at TIMESTAMPTZ,
  last_application_at TIMESTAMPTZ,

  -- Risk summary
  overall_risk_level TEXT DEFAULT 'none',
  active_fraud_flags INTEGER DEFAULT 0,

  -- Sync metadata
  last_synced_at TIMESTAMPTZ,
  sync_sources JSONB, -- {terra: timestamp, pathfinder: timestamp, ...}

  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Cross-system application tracking
CREATE TABLE hub_applications (
  id UUID PRIMARY KEY,
  applicant_id UUID REFERENCES applicants,
  profile_id UUID REFERENCES hub_profiles,

  -- Source identification
  source_system TEXT NOT NULL, -- 'terra', 'pathfinder', 'airtable'
  source_id TEXT NOT NULL, -- ID in source system

  -- Application data
  program_id UUID,
  program_name TEXT,
  status TEXT,
  submitted_at TIMESTAMPTZ,
  decided_at TIMESTAMPTZ,
  decision TEXT, -- 'approved', 'denied', 'pending'

  -- Benefit data (if approved)
  benefit_amount BIGINT, -- cents
  payment_date TIMESTAMPTZ,
  payment_status TEXT,

  -- Sync metadata
  last_synced_at TIMESTAMPTZ,
  raw_data JSONB,

  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),

  UNIQUE(source_system, source_id)
);

-- Unified timeline events
CREATE TABLE hub_timeline (
  id UUID PRIMARY KEY,
  profile_id UUID REFERENCES hub_profiles,
  applicant_id UUID REFERENCES applicants,

  -- Event data
  event_type TEXT NOT NULL,
  event_subtype TEXT,
  description TEXT,
  metadata JSONB,

  -- Source tracking
  source_system TEXT,
  source_id TEXT,

  occurred_at TIMESTAMPTZ NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Saved cross-reference queries
CREATE TABLE hub_saved_queries (
  id UUID PRIMARY KEY,
  name TEXT NOT NULL,
  description TEXT,
  query_type TEXT NOT NULL, -- 'address', 'bank', 'ip', 'custom'
  query_config JSONB NOT NULL,
  created_by UUID REFERENCES users,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
```

***

## UI Wireframe

### Search & Results

```
┌─────────────────────────────────────────────────────────────────┐
│  Hub                                      [User] [Settings]     │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  🔍 Search by name, email, phone, SSN, or submission ID │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  Recent Searches                     Saved Queries              │
│  ────────────────                   ─────────────              │
│  • john.doe@email.com               • Same address cluster      │
│  • SUB-2024-12345                   • Shared bank accounts      │
│  • 206-555-1234                     • High-risk IP addresses    │
│                                                                 │
│  ─────────────────────────────────────────────────────────────  │
│                                                                 │
│  Search Results for "john doe"                                  │
│  ═════════════════════════════                                 │
│                                                                 │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  John Doe                                    [View →]   │   │
│  │  john.doe@email.com • 206-555-1234                      │   │
│  │  4 applications • $6,300 received • No fraud flags      │   │
│  ├─────────────────────────────────────────────────────────┤   │
│  │  Johnny Doe                                  [View →]   │   │
│  │  johnny.d@email.com • 206-555-5678                      │   │
│  │  1 application • Pending • ⚠️ 1 fraud flag              │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

### Profile View

```
┌─────────────────────────────────────────────────────────────────┐
│  ← Back to Search                                John Doe       │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  [Overview] [Applications] [Documents] [Timeline] [Fraud]       │
│  ─────────────────────────────────────────────────────────────  │
│                                                                 │
│  Identity                              Summary                  │
│  ════════                             ═══════                  │
│  Name: John Michael Doe ✓             Total Applications: 4     │
│  DOB: 01/15/1985 ✓                    Approved: 3               │
│  SSN: ***-**-1234 ✓                   Benefits Received: $6,300 │
│  Email: john.doe@email.com            First Application: Dec '23│
│  Phone: 206-555-1234                  Last Application: Feb '24 │
│                                                                 │
│  Addresses                             Fraud Status             │
│  ═════════                            ════════════             │
│  Current:                              Risk Level: None ✓       │
│  123 Main St Apt 4                     Active Flags: 0          │
│  Seattle, WA 98101 ✓                   Cleared Flags: 1         │
│                                                                 │
│  Previous:                                                      │
│  456 Oak Ave                                                    │
│  Seattle, WA 98102                                              │
│                                                                 │
│  ─────────────────────────────────────────────────────────────  │
│                                                                 │
│  Recent Activity                                                │
│  ═══════════════                                               │
│  Feb 1   Applied to Childcare Subsidy           [Pending Docs] │
│  Jan 25  Payment received: ERA 2024 - $3,500    [Cleared]      │
│  Jan 22  Application approved: ERA 2024         [Complete]     │
│                                                                 │
│                                         [View Full Timeline →]  │
└─────────────────────────────────────────────────────────────────┘
```

***

## Integration Points

### Terra Sync

```typescript theme={null}
// Webhook from Terra on submission events
app.post('/api/webhooks/terra', async (req, res) => {
  const { event, submission, applicant } = req.body;

  await syncTerraSubmission({
    submissionId: submission.id,
    applicantId: applicant.id,
    formId: submission.formId,
    status: submission.status,
    data: submission.data,
  });

  await addTimelineEvent({
    applicantId: applicant.id,
    eventType: 'application',
    eventSubtype: event, // 'submitted', 'updated', 'approved', etc.
    sourceSystem: 'terra',
    sourceId: submission.id,
  });
});
```

### Airtable Sync

```typescript theme={null}
// Scheduled sync from Airtable
async function syncAirtableDecisions() {
  const records = await airtable.select({
    filterByFormula: `{Last Modified} > '${lastSyncTime}'`,
  });

  for (const record of records) {
    await updateApplication({
      sourceSystem: 'airtable',
      sourceId: record.id,
      status: record.fields['Status'],
      decision: record.fields['Decision'],
      notes: record.fields['Case Notes'],
    });
  }
}
```

### Sentinel Sync

```typescript theme={null}
// Fraud assessment sync
async function syncFraudAssessment(assessment: RiskAssessment) {
  await updateProfile({
    applicantId: assessment.applicantId,
    overallRiskLevel: calculateRiskLevel(assessment.overallScore),
    activeFraudFlags: assessment.flags.filter(f => f.status === 'active').length,
  });

  for (const flag of assessment.flags) {
    await addTimelineEvent({
      applicantId: assessment.applicantId,
      eventType: 'fraud_flag',
      eventSubtype: flag.status,
      description: flag.description,
      sourceSystem: 'sentinel',
    });
  }
}
```

***

## Implementation Phases

### Phase 1: Core Profile View

* Applicant search (name, email, phone)
* Basic profile display
* Terra submission sync
* Timeline view

### Phase 2: Cross-Reference

* Address-based queries
* Bank account queries
* IP address queries
* Saved query management

### Phase 3: Full Integration

* Airtable bidirectional sync
* Sentinel fraud flag sync
* Pathfinder screener data
* Benefit payment tracking

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Data Aggregation" icon="layer-group" href="/hub/core-systems/data-aggregation">
    How data is synced and unified across systems
  </Card>

  <Card title="Search & Queries" icon="magnifying-glass" href="/hub/core-systems/search">
    Search implementation and cross-reference queries
  </Card>

  <Card title="Timeline Events" icon="timeline" href="/hub/core-systems/timeline">
    Event types and timeline construction
  </Card>

  <Card title="Integration Guides" icon="plug" href="/hub/integrations/overview">
    Setting up data sources
  </Card>
</CardGroup>
