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.
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.
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:
Copy
Ask AI
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)
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.
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:
Copy
Ask AI
class ESOPLoan: loan_id: str principal_balance: Decimal interest_rate: Decimal suspense_shares: Decimal # ← Directly owned by THIS loan
Critical: This prevents cross-contamination and ensures ERISA compliance.
from pydantic import BaseModel, Field, validatorclass 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
2. Immutability Where Appropriate
Historical snapshots are immutable; current state is mutable during processing:
Copy
Ask AI
@dataclass(frozen=True) # Immutableclass AnnualTrustSnapshot: year: int cash_balance: Decimal allocated_shares: Decimal@dataclass # Mutable during processingclass TrustCashLedger: participant_cash: Decimal unallocated_contributions: Decimal
3. Self-Documenting
Models include descriptions and constraints:
Copy
Ask AI
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)" )
4. Relationship Integrity
Models enforce referential integrity:
Copy
Ask AI
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
# To JSONtrust_json = trust.model_dump_json()# From JSONtrust = ESOPTrust.model_validate_json(trust_json)# To databasedb.save(trust.model_dump())# From databasetrust = ESOPTrust.model_validate(db.load(trust_id))