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

# Data Models Overview

> High-fidelity models that accurately reflect ESOP structures

## Model Philosophy

At Village Labs, we built our Repurchase Engine on a set of **high-fidelity data models** that we designed to accurately reflect ESOP accounting and legal structures. We believe that models should not be mere data containers; they must embody the complex relationships and rules that govern ESOP operations.

<Info>
  **Our Design Goal:** To create models that map 1:1 to real-world ESOP concepts, making the system intuitive for practitioners while maintaining the technical precision we demand.
</Info>

## Core Models

<CardGroup cols={2}>
  <Card title="ESOPTrust" icon="building-columns" href="/models/esop-trust">
    Central accounting hub for all plan assets and liabilities
  </Card>

  <Card title="TrustCashLedger" icon="wallet" href="/models/trust-cash-ledger">
    Non-fungible cash accounting by source
  </Card>

  <Card title="ESOPLoan" icon="file-invoice-dollar" href="/models/esop-loan">
    Self-contained loan with dedicated suspense shares
  </Card>

  <Card title="Participant" icon="user">
    Individual participant account and demographics
  </Card>

  <Card title="PlanRules" icon="scale-balanced" href="/models/plan-rules">
    Legal framework and compliance rules
  </Card>

  <Card title="OperatingAssumptions" icon="chart-mixed" href="/models/operating-assumptions">
    Annual strategy and financial assumptions
  </Card>
</CardGroup>

## Model Hierarchy

```mermaid theme={null}
graph TD
    ESOP[ESOPTrust] --> CASH[TrustCashLedger]
    ESOP --> LOANS[ESOPLoans[]]
    ESOP --> SHARES[Share Pools]
    
    LOANS --> LOAN1[ESOPLoan 1]
    LOANS --> LOAN2[ESOPLoan 2]
    
    LOAN1 --> SUSPENSE1[Suspense Shares]
    LOAN2 --> SUSPENSE2[Suspense Shares]
    
    PARTICIPANTS[Participants[]] --> P1[Participant 1]
    PARTICIPANTS --> P2[Participant 2]
    
    P1 --> ACCOUNT1[Account Balance]
    P2 --> ACCOUNT2[Account Balance]
    
    style ESOP fill:#29371F,color:#fff
    style CASH fill:#3D5030,color:#fff
    style LOANS fill:#3D5030,color:#fff
```

## Key Modeling Concepts

### 1. Non-Fungible Cash

**Problem:** In traditional accounting, all cash is fungible (interchangeable). But ESOP trust cash has **source-based restrictions** on use.

**Solution:** The `TrustCashLedger` segregates cash by source:

```python theme={null}
class TrustCashLedger:
    participant_cash_accounts: Decimal        # Can only be used for participant distributions
    unallocated_company_contributions: Decimal  # Flexible use per plan rules
    unallocated_forfeiture_cash: Decimal      # Restricted use (typically contributions or reallocations)
```

<Note>
  **Real-World Analog:** Think of it like a restaurant where tips (participant cash) can only go to employees, while owner contributions can be used flexibly.
</Note>

### 2. Loan-Owned Suspense Shares

**Problem:** Multiple ESOP loans each collateralized by specific shares. Shares from Loan A shouldn't be released when paying Loan B.

**Solution:** Each `ESOPLoan` directly owns its suspense shares:

```python theme={null}
class ESOPLoan:
    loan_id: str
    principal_balance: Decimal
    interest_rate: Decimal
    suspense_shares: Decimal  # ← Directly owned by THIS loan
```

<Warning>
  **Critical:** This prevents cross-contamination and ensures ERISA compliance.
</Warning>

### 3. Separation of Legal vs. Strategy

**Problem:** Mixing unchanging legal requirements with variable business decisions leads to configuration errors.

**Solution:** Two distinct input models:

<Tabs>
  <Tab title="PlanRules (Legal)">
    ```python theme={null}
    class PlanRules:
        vesting_schedule: VestingSchedule
        distribution_policy: DistributionPolicy
        diversification_rules: DiversificationRules
        cash_usage_policy: List[CashSource]
    ```

    Changes rarely, requires amendments
  </Tab>

  <Tab title="OperatingAssumptions (Strategy)">
    ```python theme={null}
    class OperatingAssumptions:
        contribution_policy: ContributionPolicy
        share_valuation: ValuationAssumptions
        repurchase_strategy: RepurchaseStrategy
        financial_projections: FinancialProjections
    ```

    Changes annually, business decisions
  </Tab>
</Tabs>

## Data Model Principles

<AccordionGroup>
  <Accordion title="1. Type Safety" icon="shield-check">
    All models use strong typing with validation:

    ```python theme={null}
    from pydantic import BaseModel, Field, validator

    class ESOPLoan(BaseModel):
        principal_balance: Decimal = Field(ge=0)
        interest_rate: Decimal = Field(ge=0, le=1)
        suspense_shares: Decimal = Field(ge=0)
        
        @validator('interest_rate')
        def reasonable_interest_rate(cls, v):
            if v > 0.20:  # 20%
                raise ValueError('Interest rate seems unreasonably high')
            return v
    ```
  </Accordion>

  <Accordion title="2. Immutability Where Appropriate" icon="lock">
    Historical snapshots are immutable; current state is mutable during processing:

    ```python theme={null}
    @dataclass(frozen=True)  # Immutable
    class AnnualTrustSnapshot:
        year: int
        cash_balance: Decimal
        allocated_shares: Decimal

    @dataclass  # Mutable during processing
    class TrustCashLedger:
        participant_cash: Decimal
        unallocated_contributions: Decimal
    ```
  </Accordion>

  <Accordion title="3. Self-Documenting" icon="book">
    Models include descriptions and constraints:

    ```python theme={null}
    class VestingSchedule(BaseModel):
        """
        Defines how participants earn ownership of their ESOP accounts.
        
        Common schedules:
        - Graded: Gradual vesting over 2-6 years
        - Cliff: All-or-nothing after 3 years
        """
        type: Literal['graded', 'cliff']
        years_to_full_vesting: int = Field(
            ge=2, le=7,
            description="Years until 100% vested (ERISA limits: 2-7)"
        )
    ```
  </Accordion>

  <Accordion title="4. Relationship Integrity" icon="link">
    Models enforce referential integrity:

    ```python theme={null}
    class ESOPTrust:
        loans: List[ESOPLoan]
        
        def total_suspense_shares(self) -> Decimal:
            """Sum suspense shares across all loans."""
            return sum(loan.suspense_shares for loan in self.loans)
        
        def validate_share_conservation(self):
            """Ensure total shares equal allocated + suspense + unallocated."""
            total = (
                self.allocated_shares + 
                self.total_suspense_shares() + 
                self.unallocated_shares
            )
            assert total == self.total_shares_outstanding
    ```
  </Accordion>
</AccordionGroup>

## Model Lifecycle

Models flow through distinct lifecycle stages:

<Steps>
  <Step title="Configuration">
    User provides input data (PlanRules, OperatingAssumptions, InitialState)
  </Step>

  <Step title="Validation">
    Models are validated for completeness, consistency, and legal compliance
  </Step>

  <Step title="Processing">
    Engine manipulates mutable models during annual simulation cycle
  </Step>

  <Step title="Snapshot">
    End-of-year state captured as immutable snapshot
  </Step>

  <Step title="Persistence">
    Snapshot saved to database with full audit trail
  </Step>
</Steps>

## Common Patterns

### Composition Over Inheritance

Models favor composition for flexibility:

```python theme={null}
class ESOPTrust:
    cash_ledger: TrustCashLedger      # ← Composed
    loans: List[ESOPLoan]              # ← Composed
    share_pool: SharePool              # ← Composed
    
    # Not inheritance:
    # class ESOPTrust(CashLedger, LoanContainer, ShareManager)
```

### Builder Pattern for Complexity

Complex models use builders:

```python theme={null}
trust = (
    ESOPTrustBuilder()
    .with_cash_ledger(initial_cash=100_000)
    .add_loan(
        principal=2_000_000,
        rate=0.065,
        term_years=10,
        suspense_shares=20_000
    )
    .with_allocated_shares(30_000)
    .build()
)
```

### Factory Methods for Common Scenarios

```python theme={null}
# Standard graded vesting
vesting = VestingSchedule.standard_graded()

# Quick cliff vesting
vesting = VestingSchedule.cliff(years=3)

# Custom
vesting = VestingSchedule(
    type='graded',
    schedule=[0, 0, 20, 40, 60, 80, 100]
)
```

## Serialization & Deserialization

All models support JSON serialization:

```python theme={null}
# To JSON
trust_json = trust.model_dump_json()

# From JSON
trust = ESOPTrust.model_validate_json(trust_json)

# To database
db.save(trust.model_dump())

# From database
trust = ESOPTrust.model_validate(db.load(trust_id))
```

## Model Documentation

Each model includes comprehensive documentation:

* **Field descriptions**: What each field represents
* **Constraints**: Valid ranges and rules
* **Examples**: Common use cases
* **Related models**: How models connect
* **Legal context**: ERISA/IRS requirements

## Next Steps

<CardGroup cols={3}>
  <Card title="ESOPTrust" icon="building-columns" href="/models/esop-trust">
    The central accounting hub
  </Card>

  <Card title="TrustCashLedger" icon="wallet" href="/models/trust-cash-ledger">
    Non-fungible cash tracking
  </Card>

  <Card title="ESOPLoan" icon="file-invoice-dollar" href="/models/esop-loan">
    Loan-specific suspense shares
  </Card>

  <Card title="PlanRules" icon="scale-balanced" href="/models/plan-rules">
    Legal framework schema
  </Card>

  <Card title="OperatingAssumptions" icon="chart-mixed" href="/models/operating-assumptions">
    Strategy configuration
  </Card>

  <Card title="API Schemas" icon="code" href="/api-reference/schemas/plan-rules">
    Full API schema reference
  </Card>
</CardGroup>
