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

# Core Concepts

> Mental models for understanding Pathfinder's benefits matching architecture

# Core Concepts

> Before diving into code, understand the mental models that shape how Pathfinder matches people to benefits.

Pathfinder transforms the chaotic landscape of government benefits into a structured discovery experience. To work effectively with the codebase, internalize these five core concepts.

***

## 1. Programs Are Structured Data

Every benefit program—from federal SNAP to local utility assistance—is stored as a structured record with consistent fields. This enables searching, filtering, and automated eligibility checking.

```typescript theme={null}
interface Program {
  id: string;
  name: string;                    // "Supplemental Nutrition Assistance Program"
  shortName: string;               // "SNAP"
  category: ProgramCategory;       // "food_assistance"
  agency: string;                  // "USDA Food and Nutrition Service"

  // Geographic scope
  coverageType: "federal" | "state" | "county" | "city";
  coverageStates: string[];        // ["CA", "TX", "NY"] or ["*"] for all
  coverageFips: string[];          // County FIPS codes for local programs

  // Eligibility
  eligibilityRules: EligibilityRule[];
  incomeLimit: IncomeLimit | null;

  // Impact
  benefitValueCents: number | null;
  benefitFrequency: "monthly" | "annual" | "one_time";

  // Content
  description: string;
  shortDescription: string;
  howToApply: ApplyStep[];
  requiredDocuments: DocumentRequirement[];

  // Search
  searchVector: tsvector;          // PostgreSQL full-text search
  tags: string[];
}
```

**What this means for you:**

* Programs live in the `programs` table with a consistent schema
* Adding new fields doesn't require code changes—just database columns
* The `search_vector` column enables fast full-text search with ranking
* Geographic filtering uses FIPS codes for precision

See [Programs Database](/pathfinder/core-systems/programs-database) for the full schema.

***

## 2. Eligibility Is Rule-Based

Each program has eligibility rules stored as JSON. The screener collects household data, then evaluates these rules to determine potential eligibility.

```mermaid theme={null}
flowchart LR
    subgraph Screener
        Q1[Household Size] --> Q2[Monthly Income]
        Q2 --> Q3[Citizenship Status]
        Q3 --> Q4[Age/Demographics]
    end

    subgraph Matcher
        Rules[Program Rules]
        Data[Household Data]
        Rules --> Engine{Eligibility Engine}
        Data --> Engine
        Engine --> Result[Match Score]
    end

    Q4 --> Data
```

Rules follow a composable structure:

```typescript theme={null}
interface EligibilityRule {
  field: string;        // "household_income_monthly"
  operator: Operator;   // "less_than_or_equal"
  value: number | string | boolean;

  // Optional: for compound rules
  conjunction?: "AND" | "OR";
  children?: EligibilityRule[];
}

// Example: SNAP eligibility
const snapRules: EligibilityRule[] = [
  {
    field: "household_income_monthly",
    operator: "less_than_fpl_percent",
    value: 130  // 130% of Federal Poverty Level
  },
  {
    field: "citizenship_status",
    operator: "in",
    value: ["citizen", "qualified_alien", "refugee"]
  },
  {
    field: "resources",
    operator: "less_than",
    value: 250000  // $2,500 in cents
  }
]
```

**What this means for you:**

* Rules are data, not code—you can update eligibility without deploys
* The engine handles FPL calculations based on household size
* "Maybe eligible" is a valid result when data is incomplete
* Programs without explicit rules are assumed "possibly eligible"

See [Eligibility Engine](/pathfinder/core-systems/eligibility-engine) for the matching algorithm.

***

## 3. Screening Is Progressive

Users don't answer all questions upfront. The screener progressively refines matches as more information is provided.

```mermaid theme={null}
sequenceDiagram
    participant U as User
    participant S as Screener
    participant M as Matcher
    participant P as Programs

    U->>S: Start screener
    S->>M: Match with minimal data
    M->>P: Query all programs
    P->>M: 2,500 programs
    M->>S: "You may qualify for 2,500+ programs"

    U->>S: Enter ZIP code
    S->>M: Refine match
    M->>P: Filter by geography
    P->>M: 847 programs
    M->>S: "847 programs in your area"

    U->>S: Enter household info
    S->>M: Apply income rules
    M->>P: Filter by eligibility
    P->>M: 23 likely matches
    M->>S: "You likely qualify for 23 programs"
```

Each step:

1. Collects one piece of information
2. Immediately updates the match count
3. Shows progress toward personalized results

**What this means for you:**

* The screener state tracks partial answers
* Match queries run after each step (debounced)
* Empty fields don't disqualify—they reduce confidence
* Users can skip steps and return later

***

## 4. Geography Is Hierarchical

Benefits exist at multiple levels: federal, state, county, city. A user in Austin, Texas might qualify for:

* Federal programs (SNAP, Medicaid)
* Texas state programs (CHIP, TWC)
* Travis County programs (housing assistance)
* City of Austin programs (utility assistance)

```mermaid theme={null}
flowchart TD
    User[User in Austin, TX] --> Geo{Geography Resolver}
    Geo --> Fed[Federal Programs]
    Geo --> State["Texas State Programs"]
    Geo --> County["Travis County Programs"]
    Geo --> City["Austin City Programs"]

    Fed --> All[All Matched Programs]
    State --> All
    County --> All
    City --> All
```

Geographic resolution:

1. **ZIP to Coordinates**: Geocode via Nominatim
2. **Coordinates to FIPS**: Point-in-polygon to county FIPS code
3. **FIPS to Programs**: Filter programs by coverage area

```sql theme={null}
-- Programs available in Travis County, TX
SELECT * FROM programs
WHERE coverage_type = 'federal'
   OR (coverage_type = 'state' AND 'TX' = ANY(coverage_states))
   OR (coverage_type = 'county' AND '48453' = ANY(coverage_fips))
   OR (coverage_type = 'city' AND '48453' = ANY(coverage_fips)
       AND service_area @> '{"city": "Austin"}');
```

**What this means for you:**

* Always store FIPS codes, not just city/state names
* Use the `geocoding.ts` utilities for ZIP resolution
* Some programs serve multiple counties—use array containment
* Federal programs use `coverage_states = ['*']` for "all states"

***

## 5. Trust Is Earned Through Stories

Government benefits carry stigma. Many people won't apply because they feel ashamed or assume "those programs aren't for people like me." Success stories counter this by showing real people—with faces and names—who benefited.

```mermaid theme={null}
flowchart LR
    subgraph Story Pipeline
        Submit[User Submits Story]
        Queue[Moderation Queue]
        Review[Staff Review]
        Publish[Published Story]
    end

    subgraph Display
        Featured[Homepage Featured]
        Program[Program Detail Page]
        Browse[Stories Browse Page]
    end

    Submit --> Queue
    Queue --> Review
    Review -->|Approve| Publish
    Review -->|Reject| Notify[Notify User]

    Publish --> Featured
    Publish --> Program
    Publish --> Browse
```

Story data model:

```typescript theme={null}
interface SuccessStory {
  id: string;
  authorName: string;
  isAnonymous: boolean;

  // Content
  title: string;
  story: string;           // Full narrative
  quote: string | null;    // Pull quote for cards

  // Association
  programId: string | null;
  benefitReceivedCents: number | null;

  // Moderation
  status: "pending" | "approved" | "rejected" | "featured";
  moderatedBy: string | null;
  rejectionReason: string | null;

  // Engagement
  viewCount: number;
  helpfulCount: number;
}
```

**What this means for you:**

* Stories require moderation before publishing
* Anonymous stories show "Anonymous" but we track `author_id` for editing
* The `quote` field enables compact display in carousels
* `helpfulCount` uses deduplicated voting (one per user/session)

See [Success Stories](/pathfinder/features/success-stories) for implementation details.

***

## How These Concepts Connect

```mermaid theme={null}
flowchart TD
    subgraph User Journey
        Discover[Browse Programs]
        Screen[Take Screener]
        Dashboard[Track Applications]
    end

    subgraph Data Layer
        Programs[(Programs DB)]
        Rules[(Eligibility Rules)]
        Profiles[(User Profiles)]
    end

    subgraph Matching
        Geo[Geography Resolver]
        Engine[Eligibility Engine]
    end

    subgraph Engagement
        Stories[Success Stories]
        Notifs[Notifications]
        Calendar[Calendar Sync]
    end

    Discover --> Programs
    Screen --> Rules
    Screen --> Engine
    Engine --> Geo
    Dashboard --> Profiles
    Dashboard --> Notifs
    Dashboard --> Calendar
    Programs --> Stories
```

A typical user flow:

1. User arrives at Pathfinder, browses programs by category
2. Starts screener, enters ZIP code
3. Engine matches programs by geography
4. User provides income/household data
5. Engine applies eligibility rules
6. User sees personalized recommendations
7. User saves programs to dashboard
8. Calendar reminders for application deadlines
9. After receiving benefits, shares success story

***

## Next Steps

<CardGroup cols={2}>
  <Card title="System Map" icon="diagram-project" href="/pathfinder/foundation/system-map">
    Visual overview of all Pathfinder components
  </Card>

  <Card title="Programs Database" icon="database" href="/pathfinder/core-systems/programs-database">
    Deep dive into the programs schema
  </Card>
</CardGroup>
