Domain · Specifications

Lakshmi Domain — Technical Specifications

of the Oshun monorepo.

17sections38 minread

On this page

Status#

IMPLEMENTED. Lakshmi (TODO Phase 61) is the personal-finance bounded context of the Oshun monorepo. It is realized as 24 TypeScript libraries under libs/lakshmi/* and 6 service applications under apps/lakshmi/*. This document specifies the domain exactly as it exists in source: every entity, enum, state machine, API endpoint, event, table, and configuration input below is grounded in the named code file. Items that are explicitly deferred are labelled (planned).

The specification supersedes earlier drafts that documented only three packages and a four-field account model. The real @lakshmi/core account model is a 32-variant discriminated union; the real package map covers the full Phase 61 capability surface. Every package name, entity, field, enum value, branded ID, API endpoint, OAuth scope, Kafka event, BullMQ job/queue, database table, namespace, TimescaleDB hypertable, RLS policy, environment variable, and V2 schema in this document is traced to a real source file in libs/lakshmi/, apps/lakshmi/, or V2/services/.

Package Inventory#

Libraries (libs/lakshmi/*)#

All 24 libraries publish under the @lakshmi/* scope at version 0.1.0 with ./src/index.ts as the entry point (verified from each package.json). The table below maps each package name to its primary responsibility so you can navigate to the right library without reading every index file.

Package Responsibility
@lakshmi/core Shared types, branded IDs, Zod schemas, financial primitives, calculation engine
@lakshmi/db Drizzle ORM schema (20 PostgreSQL namespaces, 78 tables), migrations, RLS, TimescaleDB, seed data
@lakshmi/accounts Open-banking aggregation providers, sync engine, statement import, account management
@lakshmi/integrations Provider gateways (open banking, payroll, credit bureau, crypto, real-estate), GraphQL/webhook layer, MinIO storage
@lakshmi/transactions ML categorization, merchant enrichment, receipt OCR, recurring/anomaly/refund/split analysis
@lakshmi/budgeting Zero-based / category / cash-flow budget engines, forecasting, bills & subscriptions
@lakshmi/investments Portfolio aggregation, performance (TWR/MWR/XIRR), risk (VaR/CVaR), advanced analytics, rebalancing
@lakshmi/tax Tax-loss harvesting, income-tax optimization, deduction/credit optimization, year-round planning
@lakshmi/debt Debt inventory, payoff optimization, refinancing analysis
@lakshmi/credit Credit-score tracking/simulation, bureau dispute workflows, optimization, identity-theft recovery
@lakshmi/retirement Monte Carlo projection, Social Security optimization, RMD, decumulation, healthcare/longevity
@lakshmi/insurance Coverage portfolio, gap detection, premium optimization, claims, Medicare/LTC/disability analysis
@lakshmi/estate Asset inventory, beneficiary tracking, document vault, trust/probate/gift-tax analysis
@lakshmi/real-estate Automated valuation, equity/portfolio dashboards, mortgage, rental, depreciation, 1031 exchange
@lakshmi/crypto Multi-chain wallet aggregation, DeFi monitoring, crypto tax lots, NFT, staking, Form 8949
@lakshmi/income Equity compensation (RSU/ISO/NSO/ESPP), AMT, pay-stub analysis, freelance, multi-stream income
@lakshmi/goals Financial goal planning, milestones, probability scoring, life-event detection, trade-off analysis
@lakshmi/household Multi-user RBAC, account designation, advisor portal, secure report sharing, joint planning
@lakshmi/business Self-employment finance, entity structure, quarterly tax automation, S-Corp/QBI analysis
@lakshmi/ai-engine AI financial agents, conversational/voice query, recommendation generation, insight narration
@lakshmi/behavioral Financial-health scoring, impulse detection, nudges, peer benchmarking, weekly reflection
@lakshmi/security AES encryption, key derivation/rotation, RBAC, MFA, GDPR/CCPA/SOC2, ZK/homomorphic/federated primitives
@lakshmi/reporting Financial reports, net-worth/balance-sheet/cash-flow statements, exports, shareable links
@lakshmi/alerts Real-time alert engines, multi-channel delivery, custom alert rules

Service Applications (apps/lakshmi/*)#

The six service applications form the runtime boundary of the domain. Together they handle HTTP/WebSocket traffic, open-banking polling, AI orchestration, background jobs, recurring scheduling, and the browser extension.

App Package name Role Port
api-gateway lakshmi-api-gateway Hono HTTP/WebSocket gateway — auth, routing, rate limiting, public REST API, Kafka event bus 4200
sync-engine lakshmi-sync-engine Account sync — open-banking polling, transaction ingestion 4201
ai-agents lakshmi-ai-agents AI financial-agent orchestration — scenario modeling, recommendations 4202
worker lakshmi-worker BullMQ background worker — categorization, reports, exports, enrichment
scheduler lakshmi-scheduler BullMQ repeatable-job scheduler — recurring syncs and maintenance 3804
browser-extension lakshmi-browser-extension Browser extension (manifest.json, background/content/popup)

Future Contracts#

Cross-domain contracts are published under @contracts/lakshmi (planned; referenced in features.md, not yet present in source).

Core Domain Model (@lakshmi/core)#

@lakshmi/core is the foundation every other library builds on. It exports caching infrastructure, Prometheus metrics, financial primitives, domain types, and a financial calculation engine. Source files are organized under index.ts, types/, primitives/, and calculations/.

Branded Identifier Types#

One of the most important safety guarantees in @lakshmi/core is compile-time ID correctness. The Brand<T, B> pattern (T & { readonly [__brand]: B }) makes each ID type unique so a UserId cannot be accidentally passed where an AccountId is expected — the TypeScript compiler catches the mistake before runtime.

Branded type Underlying Defined in Constructor
UserId string types/user.ts toUserId
HouseholdId string types/user.ts toHouseholdId
AdvisorId string types/user.ts toAdvisorId
AdvisorAccessTokenId string types/user.ts (cast)
AccountId string types/account.ts toAccountId
ConnectionId string types/account.ts toConnectionId
InstitutionId string types/account.ts toInstitutionId
ManualAssetId string types/account.ts toManualAssetId

The FinancialAccount Discriminated Union#

FinancialAccount (types/account.ts) is the central type of the domain. It is a discriminated union over the type field, with 32 account variants across 8 categories. Using a discriminated union means every code path that handles an account must handle every variant — exhaustive pattern matching prevents silent bugs when new account types are added.

Every monetary field is stored as integer cents (USD minor units) to avoid floating-point drift; every date is an ISO 8601 string.

The two classification enums that appear across all variants:

  • AccountCategory — high-level category tag, one of: depository, credit, loan, investment, crypto, real_estate, business, manual.
  • AccountSignasset or liability; drives net-worth contribution sign. Assets add to net worth; liabilities subtract.

Shared base (AccountBase)#

Every variant extends AccountBase, which holds the fields common to all 32 types:

id: AccountId, userId: UserId, householdId?: HouseholdId, name, officialName?, institutionId: InstitutionId, connectionId?: ConnectionId, currency (ISO 4217), includeInNetWorth: boolean, isSharedWithHousehold: boolean, tags: string[], status (one of active, inactive, closed, frozen, pending), openedDate?, closedDate?, createdAt: Date, updatedAt: Date.

Depository variants (sign: 'asset', category: 'depository')#

Depository accounts hold liquid cash. The four variants differ primarily in their interest-earning and withdrawal constraints.

  • CheckingAccount (type: 'checking') — maskedAccountNumber, routingNumber?, availableBalanceCents, currentBalanceCents, overdraftProtection, monthlyFeeCents.
  • SavingsAccount (type: 'savings') — adds apy (decimal), monthlyTransactionLimit? (Regulation D-era).
  • CertificateOfDepositAccount (type: 'certificate_of_deposit') — apy, termMonths, openedDate, maturityDate, earlyWithdrawalPenaltyCents?, autoRollover.
  • MoneyMarketAccount (type: 'money_market') — apy, minimumBalanceCents?.

Credit variant#

The single credit variant tracks revolving credit-card debt and rewards.

  • CreditCardAccount (type: 'credit_card', category: 'credit', sign: 'liability') — creditLimitCents, currentBalanceCents, availableCreditCents, minimumPaymentCents, statementBalanceCents?, nextPaymentDueDate?, lastStatementCloseDate?, purchaseApr, cashAdvanceApr?, balanceTransferApr?, annualFeeCents, rewardsType? (cash_back | points | miles | none), rewardsBalance?, rewardsUnit? (cents | points | miles).

Loan variants (category: 'loan', sign: 'liability')#

All loan variants extend LoanBase, which adds installment-loan fields shared across every loan type:

originalBalanceCents, currentBalanceCents, monthlyPaymentCents, minimumPaymentCents?, interestRate, nextPaymentDueDate?, originationDate, maturityDate, servicer?, remainingPayments?, totalInterestPaidCents?.

The five loan variants add type-specific fields on top of LoanBase:

  • MortgageAccount (type: 'mortgage') — mortgageType (fixed | arm | interest_only | balloon), propertyAddress?, propertyValueCents?, originalLtv?, pmiRequired, pmiMonthlyCents?, pmiDropThreshold?, armPeriodicCap?, armLifetimeCap?, armNextAdjustmentDate?.
  • AutoLoanAccount (type: 'auto_loan') — optional vehicle object (year, make, model, trim?, vin?, currentValueCents?), isLease, residualValueCents?, mileageAllowance?.
  • StudentLoanAccount (type: 'student_loan') — loanType (federal_subsidized, federal_unsubsidized, federal_plus, federal_grad_plus, private), repaymentPlan? (standard, graduated, extended, ibr, paye, repaye, save, icr), incomeBasedPaymentCents?, pslfQualifyingPayments?, pslfTotalRequired?, autoPayEnrolled, projectedForgivenessDate?.
  • PersonalLoanAccount (type: 'personal_loan') — purpose? (debt_consolidation, home_improvement, medical, vacation, other).
  • HelocAccount (type: 'heloc') — creditLimitCents, currentBalanceCents, availableCreditCents, currentApr, indexRate?, margin?, drawPeriodEndDate?, repaymentEndDate?, phase (draw | repayment), minimumPaymentCents?.

Investment variants (category: 'investment', sign: 'asset')#

Investment accounts hold securities and retirement assets. All investment variants extend InvestmentAccountBase, which adds portfolio-level tracking fields:

currentValueCents, costBasisCents?, unrealizedGainLossCents?, dailyChangeCents?, dailyChangePercent?, custodian, primaryBeneficiary?, contingentBeneficiary?.

The 14 investment variants cover taxable and tax-advantaged accounts:

  • BrokerageAccount (type: 'brokerage') — marginEnabled, marginBalanceCents?, cashBalanceCents, accountOwnership (individual | joint | corporate | trust).
  • TraditionalIraAccount (type: 'traditional_ira') — annualContributionLimitCents, ytdContributionsCents, totalContributionsCents?, rmdStartAge: 73, estimatedRmdCents?.
  • RothIraAccount (type: 'roth_ira') — contribution fields plus fiveYearRuleSatisfied, firstContributionYear?.
  • SepIraAccount (type: 'sep_ira') and SimpleIraAccount (type: 'simple_ira', adds employerMatchPercent?).
  • Account401k (type: '401k') — ytdEmployerMatchCents?, employerMatchDescription?, vestingSchedule? (immediate, cliff_1yr, cliff_2yr, cliff_3yr, graded_2yr, graded_6yr), vestedPercent?, vestedValueCents?, hasRothComponent, rothBalanceCents?, loanBalanceCents?, isSafeHarbor?.
  • Account403b (type: '403b') — like 401k plus specialCatchUpAvailable? (15-year catch-up).
  • Account457b (type: '457b') — planType (governmental | non_governmental), hasInsolvencyRisk?.
  • HsaAccount (type: 'hsa') — isInvested, cashBalanceCents, investedBalanceCents, hdhpDeductibleCents?, hasEmployerContributions, ytdEmployerContributionCents?.
  • FsaAccount (type: 'fsa') — fsaType (healthcare | dependent_care | limited_purpose), currentBalanceCents, planYearEndDate, gracePeriodEndDate?, rolloverMaxCents?.
  • Account529Plan (type: '529_plan') — beneficiaryName, beneficiaryUserId?, beneficiaryDateOfBirth?, planState, stateTaxDeductionLimitCents?, ytdContributionsCents, totalContributionsCents?, isAbleAccount.
  • UtmaUgmaAccount (type: 'utma_ugma') — accountType (utma | ugma), minorName, minorUserId?, minorDateOfBirth?, governingState, transferAge (18 | 21), kiddieTextThresholdCents.
  • TrustAccount (type: 'trust') — trustName, trustType (revocable, irrevocable, charitable, special_needs, other), ein?, taxYearEnd?, isGrantorTrust.
  • PensionAccount (type: 'pension') — planType (defined_benefit | defined_contribution | cash_balance), employerName, estimatedMonthlyBenefitCents?, yearsOfService?, vestingStatus (non_vested | partially_vested | fully_vested), vestedPercent?, hasJointSurvivorOption?, colaType? (fixed_percent | cpi_linked | none), earliestRetirementDate?, normalRetirementDate?.
  • AnnuityAccount (type: 'annuity') — annuityType (fixed, variable, indexed, immediate, deferred_income), issuerName, phase (accumulation | distribution), guaranteedRate?, surrenderChargeDescription?, surrenderFreeDate?, monthlyPaymentCents?, guaranteedDeathBenefitCents?.

Crypto variants (category: 'crypto', sign: 'asset')#

Crypto accounts cover exchange holdings, self-custody wallets, and on-chain DeFi positions — three fundamentally different custody models.

  • CryptoExchangeAccount (type: 'crypto_exchange') — exchangeName, currentValueCents, cashBalanceCents, kycVerified, marginEnabled, ytdStakingRewardsCents?.
  • CryptoWalletAccount (type: 'crypto_wallet') — walletType (hardware, software, browser_extension, mobile, paper, exchange_custodial), network, publicAddress, currentValueCents, isMultiSig.
  • DefiPositionAccount (type: 'defi_position') — protocolName, network, positionType (liquidity_pool, lending, borrowing, staking, yield_farming, vault), currentValueCents, borrowedAmountCents?, collateralRatio?, liquidationThreshold?, pendingRewardsCents?, currentApy?.

Real-estate, business, and manual variants#

These variants cover assets that lack market feeds and require manual or estimated valuations.

  • RealEstateAccount (type: 'real_estate') — propertyType (primary_residence, secondary_residence, rental, commercial, land, other), structured address, currentValueCents, purchasePriceCents?, purchaseDate?, annualPropertyTaxCents?, annualInsuranceCents?, monthlyHoaFeeCents, annualRentalIncomeCents?, annualRentalExpensesCents?, valuationSource (zillow_zestimate, redfin_estimate, manual, recent_appraisal, tax_assessed), lastValuationDate, accumulatedDepreciationCents?, is1031Eligible?.
  • BusinessAccount (type: 'business') — businessName, entityType (sole_proprietorship, s_corp, c_corp, llc_single, llc_multi, partnership, nonprofit), ein?, ownershipPercent, currentValueCents, valuationMethod (revenue_multiple, ebitda_multiple, dcf, book_value, manual), annualRevenueCents?, annualEbitdaCents?, lastValuationDate?.
  • ManualAssetAccount (type: 'manual_asset') — assetCategory (ManualAssetCategory: vehicle, jewelry, art, collectible, private_equity, angel_investment, business_equity, life_insurance_cv, other_asset), currentValueCents, valuationMethod (ValuationMethod: fixed, market_linked, appreciation_rate, custom_schedule), annualAppreciationRate?, marketLinkSymbol?, revaluationSchedule?, plus identifiers.
  • ManualLiabilityAccount (type: 'manual_liability', sign: 'liability') — liabilityCategory (ManualLiabilityCategory: personal_debt, irs_tax_liability, legal_judgment, informal_loan, other_liability), currentBalanceCents, interestRate, monthlyPaymentCents?, expectedResolutionDate?.

Account helper functions#

A set of utility functions work across all 32 variants:

isAssetAccount, isLiabilityAccount, getNetWorthContributionCents (negates the balance for liabilities), and getAccountBalanceCents (a 30-case switch returning currentBalanceCents or currentValueCents per variant). FinancialAccountType is the union of all type discriminants.

Account-Adjacent Entities#

These types model the real-time state and institutional metadata that surround an account but are not part of the account itself.

  • AccountBalance — point-in-time snapshot: accountId, currency, currentCents, availableCents (nullable), limitCents (nullable), pendingDebitsCents, pendingCreditsCents, asOf (ISO 8601), isProviderDirect, optional history (NumericTimeSeries).
  • AccountConnectionid: ConnectionId, userId, institutionId, provider: AggregationProvider, providerItemId?, accessTokenRef?, status: ConnectionStatus, sync timestamps, error?: ConnectionError, linkedAccountCount, consentExpiresAt? (PSD2/CDR), webhooksEnabled, supportsHistoricalBackfill, earliestTransactionDate?.
  • ConnectionErrorcode, message, userActionRequired, suggestedAction?, firstOccurredAt, consecutiveFailures.
  • Institutionid: InstitutionId, name, displayName?, logoUrl?, websiteUrl?, routingNumber?, swiftCode?, fdicCertificateNumber?, ncuaCharterNumber?, isCreditUnion, countryCodes, supportedAccountTypes, providerCoverage (InstitutionProviderCoverage[]), composite reliabilityScore (1–100), customerServicePhone?, lastUpdatedAt.
  • ManualAsset — standalone non-aggregated asset record (distinct from ManualAssetAccount): id: ManualAssetId, userId, name, category, valuation fields, and an estimatedValueAt? function. The exported projectManualAssetValue(asset, atDate) computes projected value for fixed (unchanged), appreciation_rate (compound growth), custom_schedule (last entry at/before target); returns null for market_linked.

AggregationProvider and ConnectionStatus#

These two enums control which provider feeds an account and what state that feed is in. Understanding them is essential when working on the sync engine or connection health checks.

  • AggregationProviderplaid, yodlee, mx, finicity, tink, manual.
  • ConnectionStatusactive (syncing normally), degraded (partial data), disconnected (re-authentication required), pending_mfa, pending_oauth, revoked (token revoked by institution or user), error (unrecoverable).

Institution.providerCoverage entries (InstitutionProviderCoverage) carry provider, reliabilityScore (1–5), supportsInvestments, supportsOAuth, supportsWebhooks.

User & Identity Model (types/user.ts)#

The user model captures everything Lakshmi needs to know about a subscriber beyond their financial accounts: authentication state, subscription tier, household membership, and the privacy settings that govern what data Lakshmi is allowed to use.

  • SubscriptionTierfree, premium, family. TIER_ORDER maps these to 0/1/2; tierAtLeast does ordered comparison. SubscriptionTierConfig is a discriminated union with per-tier feature flags (maxLinkedAccounts, aiCategorization, taxOptimization, investmentAnalytics, householdManagement, estatePlanning, advisorPortal, dataExport, …); free caps linked accounts at 5, premium/family are uncapped (null). TIER_CONFIGS holds the three concrete configs.
  • AuthMetadataoshunUid, email, emailVerified, phoneNumber?, phoneVerified, mfaMethods (array of totp | sms | backup_codes), lastLoginAt?, failedLoginAttempts, lastFailedLoginAt?, lockedUntil?.
  • NotificationChannelpush, email, sms, in_app.
  • NotificationPreferences — global enabled kill switch, per-channel booleans, optional quietHours (start/end/timezone), and per-event overrides for transactionNew, budgetAlert, balanceUpdate, creditScoreChange, goalMilestone, aiRecommendation, syncError, securityAlert.
  • PrivacySettingsallowAggregateAnalytics, allowModelTraining, allowPeerBenchmarking, shareWithHousehold, dataRetentionMonths?, and a GDPR/CCPA consent record (version, grantedAt, ipAddress).
  • OnboardingStepprofile, financial_profile, link_first_account, set_budget, set_goal, explore_insights, completed. OnboardingState tracks currentStep, completedSteps, profileCompleteness (0–100), startedAt, completedAt?, skippedSteps.
  • FinancialProfileSummarynetWorthCents, monthlyGrossIncomeCents, monthlySavingsRate, totalDebtCents, emergencyFundMonths, primaryCreditScore?, estimatedEffectiveTaxRate?, asOfDate.
  • LakshmiUserid: UserId, auth: AuthMetadata, name, dateOfBirth?, residence (stateCode/country/timezone), tier, billing (statusactive | past_due | canceled | trialing | paused), householdId?, householdRole?, onboarding, financialSummary?, notifications, privacy, createdAt, updatedAt, deletedAt? (soft-delete for GDPR right-to-erasure).

Household Model (types/user.ts)#

The household model lets multiple users share a financial view while preserving fine-grained access control. An owner can see everything; a viewer sees only what has been explicitly shared with them; a child account is managed by a guardian.

  • HouseholdMemberRoleowner, admin, member, viewer, child.
  • HouseholdMemberuserId, role, joinedAt, sharedAccountIds, accountVisibility (full | summary_only | hidden), status (active | pending_invite | revoked), inviteEmail?, invitedAt?, inviteExpiresAt?.
  • HouseholdAccountDesignationindividual, shared, hidden, managed_child. HouseholdSharedAccountDesignation binds an account to a designation, visibleToRoles, and transactionVisibility (full | category_summary | balance_only | hidden).
  • JointBudgetConfigjointCategories, splitCategories (Plaid PFC codes), splitRatio.
  • Householdid: HouseholdId, name, members, ownerId, jointBudget?, sharedAccountIds, accountDesignations, sharedGoalIds, effectiveTier (max tier among members), locale (currency/dateFormat/timezone), and a settings block (requireOwnerApprovalForSharedAccounts, allowChildAccounts, defaultMemberAccountVisibility, advisorAccessAllowed).

Financial Profile (types/user.ts)#

The financial profile is the intelligence layer's input: risk tolerance, income, tax situation, and retirement assumptions. It is distinct from the user record because it can be updated independently as a user's life circumstances change.

  • TaxFilingStatussingle, married_filing_jointly, married_filing_separately, head_of_household, qualifying_surviving_spouse.
  • EmploymentTypew2_employee, self_employed_sole_proprietor, self_employed_s_corp, self_employed_c_corp, self_employed_llc, contractor_1099, partnership, retired, student, unemployed, other.
  • FinancialLiteracyLevelbeginner, intermediate, advanced, expert.
  • IncomeBracketunder_30k, 30k_50k, 50k_75k, 75k_100k, 100k_150k, 150k_200k, 200k_500k, over_500k.
  • RiskToleranceProfilescore (1 conservative – 10 aggressive), label (very_conservative, conservative, moderate, moderately_aggressive, aggressive, very_aggressive), questionnaireResponses (exactly 8 responses, derived from an 8-question horizon/reaction/stability/liquidity/experience/goal/DTI/emergency-fund questionnaire), assessedAt, manualOverride.
  • FinancialProfileuserId, riskTolerance, incomeBracket, grossAnnualIncomeCents?, taxFilingStatus, employmentType, stateOfResidence, financialLiteracyLevel, targetRetirementAge?, plannedSocialSecurityClaimAge?, hasPension, pensionMonthlyIncomeCents?, createdAt, updatedAt.

Advisor Access (types/user.ts)#

Financial advisors need to see a client's full picture to give good advice, but that access must be bounded, audited, and revocable. The AdvisorAccess model encodes all three constraints.

  • AdvisorPermissionScopeaccounts:read, transactions:read, investments:read, tax:read, retirement:read, estate:read, insurance:read, income:read, debt:read, credit:read, goals:read, reports:generate, ai:query.
  • AdvisorAccessid: AdvisorAccessTokenId, clientUserId, advisorUserId, advisorFirmName?, scopes, grantedAt, expiresAt (mandatory — advisor access is never indefinite), revokedAt?, grantReason?, an accessLog array (audit trail of data accesses), and a reportLinks array (presigned report-sharing links with download limits).

Runtime Validation (Zod schemas)#

@lakshmi/core ships runtime Zod schemas that mirror the structural TypeScript types, catching invalid data at API boundaries and during deserialization before it can corrupt internal state:

SubscriptionTierSchema, HouseholdMemberRoleSchema, TaxFilingStatusSchema, EmploymentTypeSchema, and FinancialProfileSchema (which enforces the 8-element questionnaireResponses, score range 1–10, two-letter stateOfResidence, targetRetirementAge 50–90, plannedSocialSecurityClaimAge 62–70). FinancialProfileInput is the inferred input type.

Financial Primitives (primitives/)#

The primitives barrel provides the building blocks for all monetary calculations in the domain. They are designed to be used directly in business logic without reaching for external libraries.

  • Money — immutable value object holding integer amountMinor plus an ISO 4217 currency. Constructors: fromMinor, fromDecimal (applies banker's rounding), zero. Arithmetic (add, subtract, multiply, divide) preserves currency and rejects cross-currency operations with a TypeError directing callers to ExchangeRate. allocate(ratios) and split(n) distribute remainder minor units penny-by-penny so totals are conserved. Comparison, min/max/sum, locale-aware format/ formatCompact, and JSON (de)serialization are provided. CURRENCY_INFO is a 100+-entry ISO 4217 registry (code, name, symbol, decimal places, separators); bankersRound implements round-half-to-even.
  • The primitives barrel also exports ExchangeRate, DateRange, Percentage, and NumericTimeSeries / time-series utilities.

Financial Calculation Engine (calculations/)#

The calculation engine is a production-grade suite of financial math functions. It is intentionally separate from the domain types so that calculations can be tested deterministically with known inputs and expected outputs.

The calculations/ barrel exports: compound-interest (variable-rate schedules), amortization (fixed, ARM, interest-only, balloon), tvm (PV, FV, NPV, IRR, XIRR, MIRR), monte-carlo (retirement and goal simulation), tax-brackets (federal + 50-state, 2024), risk-metrics (Sharpe, Sortino, VaR, CVaR, beta, alpha), and social-security (PIA, COLA, claiming adjustments).

Integration Layer#

Account Aggregation (@lakshmi/accounts)#

@lakshmi/accounts is organized into four module groups, each re-exported from src/index.ts:

  1. providers/ — aggregation-provider adapters (one per supported aggregation service).
  2. sync/ — balance and transaction sync engine; applies to active connections only.
  3. import/ — statement import for accounts that do not support live aggregation.
  4. management/ — account lifecycle management.

The library converts open-banking connections into FinancialAccount records; balance refresh applies to active connections.

Provider & Document Integrations (@lakshmi/integrations)#

@lakshmi/integrations provides the broader provider ecosystem beyond bank aggregation: open-banking standards, payroll, tax software, insurance carriers, and document storage. The following modules are exported from src/index.ts:

open-banking-api-gateway, aggregation-provider-gateway, accounting-software-sync, tax-software-export, payroll-provider-integration, spreadsheet-sync-engine, insurance-carrier-integration, real-estate-data-provider-integration, crypto-data-provider-integration, credit-bureau-integration, graphql-api-layer, webhook-notification-system, automation-platform-connectors, and storage.

Intelligence Layer#

The intelligence layer transforms raw financial data into the categorizations, plans, recommendations, and behavioral insights that make Lakshmi useful. Each module is addressed in the subsections below.

Transaction Intelligence (@lakshmi/transactions)#

Transaction intelligence is organized into four module groups: categorization/, merchants/, receipts/, analysis/.

Categorization (categorization/) — built on a Plaid-style taxonomy (ALL_CATEGORIES, LEAF_CATEGORIES, CategoryNode, CategoryLevel). The TransactionCategorizer produces a CategorizationResult with a CategoryPrediction and a ConfidenceTier; ManualReviewQueue holds low-confidence ReviewQueueItems. PersonalizationEngine learns from CorrectionEvents into a UserPersonalizationProfile. CustomRulesEngine evaluates user CustomRules — conditions on merchant name, description, amount, account, or date pattern; actions include SetCategoryAction, AddTagsAction, SetSplitAction, and AssociateGoalAction. MultiLabelCategorizer splits a transaction across multiple CategoryAllocations.

Analysis (analysis/) provides the following engines, each responsible for a specific enrichment task:

  • RecurringTransactionDetector — emits RecurringPatterns (RecurringFrequency, RecurringType, RecurringConfidence).
  • SubscriptionManager — tracks SubscriptionRecords, PriceChangeEvents, FreeTrialEvents, with SubscriptionStatus.
  • AnomalyDetector — flags AmountAnomalyFlag, NewMerchantFlag, LocationAnomalyFlag, TimeAnomalyFlag, VelocityAnomalyFlag (union AnomalyFlag) with AnomalySeverity; zScore is the statistical core.
  • RefundMatchingEngine — matches refunds to purchases (RefundStatus, RefundMatchMethod).
  • PendingTransactionManager — predicts settlement (SettlementPrediction) and matches pending to posted transactions.
  • SplitTransactionEngine — splits transactions into SplitParts (SplitAllocationMethod, SplitDimension).
  • FeeDisaggregationEngine — separates tip/tax/platform fees from a charge.
  • InternationalTransactionAnalyzer / TravelModeManager — FX-fee detection and home-currency conversion (COUNTRY_CURRENCY map).

Receipts (receipts/) — ReceiptOcrParser and an OcrEngine abstraction extract amounts/dates/line items; AmazonOrderStore and EmailReceiptParser ingest order history; ReceiptMatchingEngine matches receipts to transactions with computeMatchConfidence; ReceiptStorageService stores encrypted receipt images (encryptBuffer/decryptBuffer, deriveReceiptDek).

Budgeting and Cash Flow (@lakshmi/budgeting)#

@lakshmi/budgeting is organized into three module groups: budget/, forecast/, bills/.

Budget engines (budget/) — ZeroBudgetEngine, CategoryBudgetEngine, CashFlowBudgetEngine, plus RolloverManager, SinkingFundManager, PaycheckPlanner, BudgetPeriodCalculator, BudgetTemplateEngine. The core type set includes:

  • Budget structure: Budget, BudgetPeriod, BudgetCategory, BudgetCategoryGroup, Envelope, BudgetAssignment, FundTransfer, RolloverMode, CategoryType.
  • Category model: BuiltinModel, BudgetBucket, BudgetBucketName, BudgetAllocationModel.
  • Cash-flow types: BillFrequency, UpcomingBill, ExpectedIncome, SafeToSpendResult, CashFlowProjection.
  • Sinking-fund types: FundingStatus, FundRecurrence, SinkingFund, ContributionSchedule.
  • Paycheck types: PaycheckFrequency, AllocationMethod, AllocationRule, PlannedPaycheck.
  • Templates: TemplateId, BudgetTemplate. DEFAULT_ROLLOVER_CONFIGS is the default rollover config set.

Cash-flow forecasting (forecast/) — CashFlowForecastEngine, SpendingVelocityTracker, PredictiveBalanceEngine, IncomeIrregularityHandler. The velocity tracker emits PaceIndicator, OverdraftRisk, CategoryVelocity, PeriodVelocitySummary; the predictive engine emits DailyBalanceProjection/PredictiveBalanceResult. Scenario helpers createJobLossScenario, createSalaryRaiseScenario, createMajorPurchaseScenario build ScenarioDefinitions for ScenarioComparison.

Bills & subscriptions (bills/) — BillCalendarEngine (BillCalendarEntry, WeekView, MonthView, BillUrgency), SubscriptionDetectionEngine (DetectedSubscription, PriceIncreaseAlert, TrialExpirationAlert, SubscriptionDashboard), BillNegotiationAssistant (NegotiationGuide, NegotiationScript), DuplicateSubscriptionDetector (OverlapGroup, BundleOption, DuplicateDetectionResult).

Behavioral Finance (@lakshmi/behavioral)#

@lakshmi/behavioral exposes PACKAGE_NAME = '@lakshmi/behavioral' and a flat module set from src/index.ts. Each export below addresses a specific dimension of financial behavior, from moment-to-moment impulse detection to multi-week habit formation.

  • Financial-health scoringCompositeFinancialHealthScorer / computeFinancialHealthScore produce a FinancialHealthScoreResult from a FinancialHealthScoreInput (credit, estate, insurance, investment, retirement inputs) with FinancialHealthDimension, FinancialHealthStatus, FinancialHealthConfidence, and a MissingFinancialHealthDataPolicy. FinancialHealthDimensionAssessor adds targeted recommendations.
  • Financial stressFinancialStressIndexDetector / detectFinancialStress produce a FinancialStressIndexResult (FinancialStressLevel, FinancialStressSignal, FinancialStressInterventionTrigger).
  • Lifestyle inflationLifestyleInflationDetector analyzes income-rise events and category drivers (LifestyleInflationSeverity, LifestyleInflationNudge).
  • ResilienceFinancialResilienceScorer (FinancialResilienceLevel, FinancialResilienceShockCapacity).
  • Spending behaviorSpendingBehaviorPatternAnalyzer detects EmotionalSpendingTrigger, PaydaySplurgePattern, TimePattern, DayOfWeekPattern, MerchantAffinityCluster.
  • Impulse detectionImpulsePurchaseDetector / detectImpulsePurchase produce an ImpulsePurchaseDetectionResult with ImpulsePurchaseCandidates, ImpulsePurchaseSeverity, ImpulseBudgetImpact/ImpulseGoalImpact, and an ImpulseReflectionPrompt.
  • NudgesFinancialNudgeEngine / generateFinancialNudges produce FinancialNudges with FinancialNudgeType, FinancialNudgeSeverity, FinancialNudgeTone, FinancialNudgeEvidence, and a FinancialNudgeActionPayload.
  • Smart defaults & savings automationSmartDefaultConfigurationEngine and SmartSavingsAutomationEngine (round-up, percentage-of-income, surplus-sweep, windfall rules; SmartSavingsTransferInstruction).
  • Loss-aversion protectionLossAversionProtectionEngine surfaces LossAversionInterventions using historical drawdown-recovery samples.
  • Habits, badges, challengesFinancialHabitStreakTracker, LakshmiAchievementBadgeSystem (LAKSHMI_BADGE_CATALOG), FinancialChallengeSystem (LAKSHMI_FINANCIAL_CHALLENGE_TEMPLATES).
  • Peer benchmarkingPeerBenchmarkingEngine / compareAgainstAnonymousPeers compare against an anonymous cohort (PeerBenchmarkSegment, PeerBenchmarkMetricType).
  • Weekly reflectionWeeklyFinancialReflectionEngine / generateWeeklyFinancialReflection assemble a reflective recap (WeeklyFinancialReflectionPrompt, WeeklyFinancialReflectionSentiment, WeeklyFinancialReflectionTrendAnalysis, WeeklyFinancialJournalEntry).

Investment Management (@lakshmi/investments)#

@lakshmi/investments is organized into five module groups: portfolio/, performance/, risk/, advanced/, rebalancing/.

  • PortfolioPortfolioAggregationEngine, SecurityMaster, AllocationAnalyzer, FundXRayEngine; identifier validation (validateCUSIP, validateISIN, classifyByTicker), GICS_SECTORS. Types include Holding, PortfolioPosition, AggregatedPortfolio, SecurityRecord, SecurityType, AssetClass, AssetSubClass, CurrentAllocation, TargetAllocation, DriftAnalysis, DriftSeverity, RebalanceSuggestion, XRayReport.
  • PerformancecomputeTWR, computeMWR, computeXIRR; BenchmarkComparisonEngine with BENCHMARK_DEFINITIONS. Types include DailyValuation, CashFlow, LookbackPeriod, TWRResult, MWRResult, XIRRResult, BenchmarkComparison, PerformanceAttribution, BHBAttributionEffect.
  • RiskRiskMetricsEngine, VaREngine; types RiskMetrics, DrawdownAnalysis, CorrelationMatrix, VaRMethod, ConfidenceLevel, VaRResult, VaRSuite.
  • AdvancedFactorAnalysisEngine, FeeImpactAnalyzer, ExposureAnalyzer, DividendIntelligenceEngine, FixedIncomeAnalyticsEngine, OptionsTracker, ESGScoringEngine, AlternativeInvestmentTracker, ConcentratedStockAnalyzer, IPSGenerator.
  • RebalancingRebalancingEngine, TaxAwareRebalancingOptimizer; RebalancingMethod, RebalancingFrequency, RebalanceTrade, RebalancingPlan, AssetLocationRecommendation.

Tax Planning (@lakshmi/tax)#

@lakshmi/tax is organized by Phase 61 sub-areas (verified from src/index.ts), covering four distinct planning horizons:

  • 61.7.1 Tax-loss harvesting (tlh/) — TLHScanner (wash-sale-aware; SUBSTANTIALLY_IDENTICAL_GROUPS, IDENTICAL_GROUP_MAP, marginalOrdinaryRate, longTermCapitalGainsRate), LotOptimizer (LotSelectionMethod, GainType), ReplacementRecommender (REPLACEMENT_DATABASE), AnnualHarvestingOptimizer (HarvestingPlan, CrossAccountCoordination). FilingStatus is the shared filing-status type.
  • 61.7.2 Income-tax optimization (income/) — BracketManager, RothLadderPlanner, EstimatedTaxCalculator, W4Optimizer (SafeHarbor analysis, UnderpaymentPenalty).
  • 61.7.3 Deduction & credit optimization (deductions/) — DeductionOptimizer (bunching, QCD, DAF strategies), AMTAnalyzer, NIITAnalyzer.
  • 61.7.4 Year-round planning (planning/) — TaxProjectionEngine, DocumentTracker (TaxDocumentType, DocumentStatus), TaxImpactSimulator, StateTaxAnalyzer (relocation/multi-state), SEOptimizer, WithdrawalSequencer (calculateRMD), TaxCalendarGenerator, TaxDeadlineReminderCalendar.

Debt and Credit#

@lakshmi/debtPACKAGE_NAME = '@lakshmi/debt'; modules inventory/, payoff/, refinancing/. Computes amortization, compares avalanche/snowball/ hybrid payoff strategies, and evaluates refinancing.

@lakshmi/creditPACKAGE_NAME = '@lakshmi/credit'. Engines: CreditScoreTracker (classifyCreditScore), AlternativeCreditDataIntegrator, CreditScoreFactorDecomposer, CreditReportMonitor, CreditReportDisputeWorkflowBuilder (recommendDisputeReasons), CreditScoreSimulator, CreditUtilizationOptimizer, AuthorizedUserStrategyAnalyzer, CreditAgeManagementTracker, OptimalCreditCardRecommender, CreditFreezeThawManager, CreditMixOptimizer, DarkWebMonitor, IdentityTheftRecoveryWorkflowBuilder. Key enums include CreditBureau, CreditScoreModel, CreditScoreModelFamily, CreditDisputeStatus, CreditScoreFactorId.

Retirement, Insurance, and Estate#

@lakshmi/retirement (PACKAGE_NAME = '@lakshmi/retirement') — FireCalculator, the Social Security suite (SocialSecurityBenefitEstimator, SocialSecurityClaimingStrategyOptimizer, SocialSecuritySpousalBenefitCoordinator, SocialSecuritySurvivorBenefitAnalyzer, SocialSecurityEarningsTestCalculator), RetirementReadinessScorer, RetirementIncomeGapAnalyzer, RetirementMonteCarloProjectionEngine, RetirementScenarioComparisonTool, RetirementContributionOptimizer, ContributionLimitTracker, EmployerMatchOptimizer, VestingScheduleTracker, RequiredMinimumDistributionCalculator, DynamicWithdrawalRateEngine, RetirementTaxWithdrawalSequencingEngine, RetirementIncomeStreamModeler, HealthcareCostProjector, LongevityRiskAnalyzer.

@lakshmi/insurance (PACKAGE_NAME = '@lakshmi/insurance') — InsurancePortfolioDashboardBuilder, InsuranceClaimsHistoryTracker, InsurancePolicyDataManager, InsuranceRenewalCalendarBuilder, InsuranceSpendDashboardBuilder, HealthInsurancePlanComparisonEngine (HSA_RULES_2026), DisabilityInsuranceAdequacyAnalyzer, LongTermCareInsuranceAnalyzer, UmbrellaLiabilityCoverageCalculator, DeductibleOptimizationEngine, CoverageGapDetector, MedicareEnrollmentPlanner, LifeInsuranceNeedsAnalyzer. Enums include InsurancePolicyCategory, InsurancePolicyType, InsurancePolicyStatus, CoverageGapKind, CoverageGapSeverity.

@lakshmi/estate (PACKAGE_NAME = '@lakshmi/estate') — EstateAssetInventoryBuilder, BeneficiaryTracker, BeneficiaryChangeImpactAnalyzer, EstatePlanLifeEventTriggerSystem, AssetTitlingAnalyzer, FederalEstateTaxProjector, StateEstateInheritanceTaxAnalyzer, GiftTaxTracker, TrustAnalysisModule, ProbateAvoidanceAnalyzer, EstateDocumentVaultBuilder (decryptEstateDocumentVersion), DigitalLegacyManager, CryptocurrencySuccessionPlanner, EmergencyAccessProtocol, ExecutorTrusteeToolkit. Key types: EstateAssetTransferStatus, BeneficiaryConflict, EstateDocumentType, EstateDocumentEncryptionMetadata, EmergencyAccessStatus, ExecutorChecklistItem.

Real Estate and Crypto#

@lakshmi/real-estate (PACKAGE_NAME = '@lakshmi/real-estate') — AutomatedHomeValuationEngine, HomeEquityDashboard, PropertyPortfolioDashboard, RealEstateAllocationTracker, PropertyTaxTracker, MortgageTracker, MortgageRefinancingAnalyzer, HomeAffordabilityCalculator, BuyVsRentAnalysisEngine, PmiRemovalTracker, RentalPropertyAnalyzer, RentalIncomeExpenseTracker, DepreciationTracker (cost-segregation, recapture), Exchange1031Planner, VacancyMaintenanceReservePlanner.

@lakshmi/crypto (PACKAGE_NAME = '@lakshmi/crypto') — MultiChainWalletAggregator (SUPPORTED_CRYPTO_CHAINS), CryptoExchangeIntegrationClient (validateCryptoExchangeReadOnlyPermissions — exchange links are read-only), DefiPositionMonitor, NftPortfolioTracker, StakingRewardTracker, CryptoTaxLotTracker, CryptoTransactionClassifier, AirdropValuationScanner, DefiTaxHandler, Form8949Generator, CryptoPortfolioIntegrator, ImpermanentLossCalculator, GasFeeAnalytics, TokenApprovalManager, WalletSecurityScorer. Enums include SupportedCryptoChain, DefiProtocolType, CryptoTransactionType, CryptoTaxLotSelectionMethod, Form8949Part.

Income, Goals, Household, and Business#

@lakshmi/income (PACKAGE_NAME = '@lakshmi/income') — MultiStreamIncomeDashboard, IncomeDetectionEngine, PassiveIncomeDashboard, PayStubAnalysisEngine, SalaryBenchmarkingEngine, ISOExerciseOptimizer, Election83bAnalyzer, ESPPAnalyzer, NSOExerciseAnalyzer, FreelanceIncomeManager, BusinessExpenseCategorizer, EntityStructureOptimizer, QuarterlyEstimatedTaxEngine, SelfEmployedRetirementOptimizer, RSUTracker. Equity-comp types include RSUVestingEvent, ISOAmtResult, ESPPDispositionType, NSOExerciseStrategy.

@lakshmi/goals (PACKAGE_NAME = '@lakshmi/goals') — MultiGoalEngine (createGoalFromTemplate), BabyChildCostPlanner, CareerChangeModeler, MajorPurchasePlanner, GoalFundingAnalysisEngine, FinancialIndependenceTracker, LifeEventAutoDetectionSystem, EmergencyFundAdequacyCalculator, EducationSavingsPlanner (COLLEGE_SCORECARD_SCHOOL_COST_FIELDS), GoalProbabilityScoringEngine, HomePurchasePlanner, GoalTradeOffAnalyzer. MultiGoalEngine types: ManagedFinancialGoal, GoalType, GoalStatus, GoalPriority, GoalMilestoneProgress, GoalTemplate.

@lakshmi/household (PACKAGE_NAME = '@lakshmi/household') — membership management (createHousehold, inviteHouseholdMember, acceptHouseholdInvitation, changeHouseholdMemberRole, removeHouseholdMember, evaluateHouseholdAccess, HOUSEHOLD_ROLE_TEMPLATES), HouseholdAccountDesignationManager, HouseholdNetWorthDashboardBuilder, HouseholdSpendingAllowancePlanner, HouseholdFinancialCalendarBuilder, ChildrenFinanceModule (CHILD_FINANCIAL_LITERACY_LESSONS), ElderCareModeBuilder, DivorceFinancialPlanner, PrenuptialTransparencyBuilder, FamilySupportTracker, AdvisorPortalAccessManager, SecureReportSharingService, AdvisorRecommendationInboxService, FamilyFinancialMeetingPrepBuilder. The household RBAC type set includes HouseholdRole, HouseholdPermission, HouseholdAccessEvaluationResult, AdvisorPermissionLevel, AdvisorPortalAccessDecision, HouseholdAuditEvent.

@lakshmi/business (PACKAGE_NAME = '@lakshmi/business') — BusinessPersonalTransactionSeparator, BusinessQuarterlyTaxAutomationEngine, HomeOfficeDeductionTracker, VehicleMileageTracker, BusinessCashFlowForecaster, BusinessValuationTracker, BusinessInvoicingReceivablesTracker, ContractorVendorManager (1099/W-9 tracking), BusinessInsuranceAnalyzer, BusinessExpenseReportGenerator, BusinessEntityStructureOptimizer, SCorpSalaryAnalyzer, SelfEmployedRetirementPlanOptimizer, QBIDeductionAnalyzer.

AI Reasoning (@lakshmi/ai-engine)#

@lakshmi/ai-engine (PACKAGE_NAME = '@lakshmi/ai-engine') sits above all other intelligence modules and orchestrates AI-driven planning. Its agents and engines:

AIFinancialAdvisorAgent (analyzeFinancialPicture), AIBillNegotiationAgent, AIAnomalyInvestigator, AIFinancialPlanGenerator, AILifeEventImpactModeler, AIOpportunityCostEngine, AIPredictiveCashFlowEngine, AISubscriptionPriceIncreasePredictor, AITaxMoveRecommender, AITaxOptimizationAgent, ConversationalFinancialQueryEngine, FinancialDataQueryCompiler, MultiTurnFinancialDialogueManager, FinancialInsightNarrator, VoiceFinancialQueryAssistant. The advisor agent produces FinancialAdvisorRecommendations carrying FinancialAdvisorConfidence, FinancialAdvisorPriority, FinancialAdvisorEffort, FinancialAdvisorImpactType, and a FinancialAdvisorDomainCoverage; the conversational engine resolves a FinancialStructuredQuery from a FinancialQueryIntent, and the query compiler emits a CompiledFinancialDataQuery with typed filters and joins.

Security Layer (@lakshmi/security)#

The security layer applies to every other layer above it. @lakshmi/security is organized into the following modules (from src/index.ts): differential-privacy, device-trust, audit-logging, biometric-auth, ccpa-compliance, data-residency, encryption, end-to-end-encryption, federated-learning, gdpr-compliance, homomorphic-analytics, mfa, rbac, session-management, soc2-compliance, zero-knowledge.

Encryption (encryption.ts)#

Encryption uses a tiered-key model so that the most sensitive data (e.g., provider access tokens) is protected by a stronger key than lower-sensitivity data (e.g., cached summaries). This limits the blast radius if one key is compromised.

  • EncryptionTierstandard, sensitive, critical; tier selects the key.
  • EncryptedPayload / KeyMetadata / DerivedKeyResult / ReEncryptionResult describe ciphertext envelopes and key state.
  • Public functions: encrypt/decrypt, encryptString/decryptString, serializePayload/deserializePayload, reEncrypt, needsRotation, getKeyRotationStatus, hmacToken/hmacTokensEqual (constant-time token comparison). LakshmiEncryptionService is the service wrapper; getEncryptionService returns the singleton.

RBAC (rbac.ts)#

Role-based access control governs what each user role can do with financial data. The advisor role is handled here alongside household roles so that advisor access uses the same evaluation pipeline as internal roles.

  • LakshmiRbacRoleowner, admin, member, viewer, child, advisor.
  • LakshmiDataCategory — finance data-category enum gating access.
  • LakshmiAccessActionview, edit, export, share.
  • LakshmiAccountVisibilityprivate, shared, household.
  • LakshmiRbacService evaluates a LakshmiAuthorizationRequest into a LakshmiAuthorizationResult with a LakshmiAccessDecisionCode; LAKSHMI_RBAC_ROLE_TEMPLATES holds per-role default permissions.

Compliance Modules#

The remaining security modules implement regulatory obligations and privacy-preserving analytics:

  • gdpr-compliance, ccpa-compliance, and soc2-compliance implement data-subject-rights, opt-out, and audit-control workflows.
  • audit-logging records access to sensitive data.
  • data-residency enforces regional storage requirements.
  • session-management, mfa, biometric-auth, and device-trust cover authentication flows.
  • differential-privacy, homomorphic-analytics, federated-learning, zero-knowledge, and end-to-end-encryption provide the privacy-preserving-analytics primitives that allow aggregate insights without exposing individual user data.

Experience Layer#

Reporting (@lakshmi/reporting)#

@lakshmi/reporting (PACKAGE_NAME = '@lakshmi/reporting') assembles data from across all capability modules into user-facing reports. Report builders (from src/index.ts):

category-spending-deep-dive, custom-dashboard-builder, debt-payoff-progress-report, financial-snapshot-one-pager, income-expense-analysis, interactive-visualization-library, investment-performance-report, net-worth-tracker, personal-balance-sheet, personal-cash-flow-statement, projected-net-worth-report, report-export-engine, scheduled-report-delivery-engine, shareable-report-links, tax-ready-report-suite, year-over-year-comparison-charts.

Alerts (@lakshmi/alerts)#

@lakshmi/alerts (PACKAGE_NAME = '@lakshmi/alerts') drives proactive financial notifications. Alert engines (from src/index.ts):

bill-due-reminder-engine, budget-threshold-alert-engine, credit-score-change-alert-engine, custom-alert-rules-engine, goal-milestone-celebration-engine, investment-rebalancing-alert-engine, large-transaction-alert-engine, low-balance-alert-engine, multi-channel-delivery-system, rate-change-alert-engine, subscription-renewal-alert-engine, unusual-activity-alert-engine.

API Surface — Public REST API#

The apps/lakshmi/api-gateway exposes a public REST API defined in src/public-rest-api.ts. Version v1; default base URL https://api.lakshmi.oshun.dev; OpenAPI document at /openapi.json (openapi: 3.1.0). All endpoints are secured by the lakshmiOAuth security scheme with per-endpoint scopes.

Authentication Flow#

Lakshmi uses OAuth 2.0 (createLakshmiOAuthAuthorizationServerMetadata):

  • Issuer — default https://auth.lakshmi.oshun.dev
  • Endpointsauthorization_endpoint: /oauth2/authorize, token_endpoint: /oauth2/token, jwks_uri: /.well-known/jwks.json
  • Supported flowsresponse_types_supported: ['code']; grant_types_supported: ['authorization_code', 'refresh_token', 'client_credentials']
  • PKCEcode_challenge_methods_supported: ['S256']
  • Client authtoken_endpoint_auth_methods_supported: ['client_secret_basic', 'private_key_jwt']

OAuth Scopes#

Every endpoint requires one or more of the following OAuth scopes. Callers receive 401 Unauthorized when the token is missing or invalid and 403 Forbidden when the token lacks a required scope.

accounts:read, accounts:write, transactions:read, transactions:write, budgets:read, budgets:write, investments:read, tax:read, debt:read, credit:read, retirement:read, insurance:read, estate:read, real_estate:read, crypto:read, income:read, goals:read, goals:write, alerts:read, alerts:write, household:read, household:write, ai:query.

Endpoints#

Every endpoint below is defined in the ENDPOINTS catalog of public-rest-api.ts (method, path, operationId, tag, required scopes). All paths are served under the /v1 prefix.

Method Path Operation Scopes
GET /accounts listAccounts accounts:read
GET /accounts/{accountId} getAccount accounts:read
GET /accounts/{accountId}/balance-history getAccountBalanceHistory accounts:read
GET /accounts/net-worth/history getNetWorthHistory accounts:read
GET /transactions listTransactions transactions:read
GET /transactions/search searchTransactions transactions:read
PATCH /transactions/{transactionId}/category updateTransactionCategory transactions:write
GET /budgets listBudgets budgets:read
POST /budgets createBudget budgets:write
GET /budgets/{budgetId}/forecast getBudgetForecast budgets:read
GET /investments/portfolios listInvestmentPortfolios investments:read
GET /investments/portfolios/{portfolioId} getInvestmentPortfolio investments:read
GET /investments/portfolios/{portfolioId}/tax-lots getInvestmentTaxLots investments:read
GET /investments/tax-loss-harvest listTaxLossHarvestOpportunities investments:read, tax:read
GET /tax/profile getTaxProfile tax:read
GET /tax/roth-conversion getRothConversionScenarios tax:read
GET /tax/brackets getTaxBrackets tax:read
GET /debt/accounts listDebtAccounts debt:read
GET /debt/payoff-plan getDebtPayoffPlan debt:read
GET /credit/scores listCreditScores credit:read
GET /credit/simulation simulateCreditScore credit:read
GET /retirement/projection getRetirementProjection retirement:read
GET /retirement/social-security getSocialSecurityOptimization retirement:read
GET /retirement/rmd getRequiredMinimumDistributions retirement:read
GET /insurance/policies listInsurancePolicies insurance:read
GET /insurance/gap-analysis getInsuranceGapAnalysis insurance:read
GET /estate/plan getEstatePlan estate:read
GET /estate/documents listEstateDocuments estate:read
GET /real-estate/properties listRealEstateProperties real_estate:read
GET /real-estate/properties/{propertyId}/rental-analysis getRentalPropertyAnalysis real_estate:read
GET /crypto/wallets listCryptoWallets crypto:read
GET /crypto/defi listDefiPositions crypto:read
GET /income/employers listIncomeEmployers income:read
GET /income/equity-grants listEquityGrants income:read
GET /income/amt-analysis getAmtAnalysis income:read, tax:read
GET /goals listGoals goals:read
POST /goals createGoal goals:write
GET /goals/{goalId}/scenarios getGoalScenarios goals:read
GET /alerts listAlerts alerts:read
PATCH /alerts/{alertId}/read markAlertRead alerts:write
GET /household getHousehold household:read
POST /household/invite inviteHouseholdMember household:write
POST /ai/query queryFinancialAi ai:query
GET /ai/recommendations listAiRecommendations ai:query

Standard responses: 200/201 success, 401 Unauthorized (missing/invalid token), 403 Forbidden (missing scope), 429 Rate-limited. Rate limiting uses a redis_sliding_window algorithm and returns X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Window, and Retry-After headers.

Real-Time WebSocket Channels#

In addition to REST, the api-gateway provides a WebSocket interface for real-time dashboard updates. apps/lakshmi/api-gateway/src/websocket.ts runs a room-based pub/sub WebSocket server (LakshmiWebSocketManager). WsMessage carries a WsMessageType; the required real-time message types (REQUIRED_REALTIME_MESSAGE_TYPES) cover balance updates, new transactions, sync status, and alerts (payloads BalanceUpdatePayload, TransactionNewPayload, SyncStatusPayload, AlertPayload). isAuthorizedRoomSubscription enforces per-user room authorization.

Domain Events (Kafka)#

Kafka events are how Lakshmi's services communicate asynchronously. The api-gateway publishes events; the worker, ai-agents, and sync-engine consume them. Typed Zod schemas for all events are defined in apps/lakshmi/api-gateway/src/events.ts; kafka.ts (LakshmiEventBus, built on kafkajs) publishes them with per-topic partitioning by userId.

Base Event Schema#

Every event extends BaseEventSchema, which provides the envelope fields common to all events: eventId (UUID), version (default '1.0'), timestamp (ISO 8601 UTC), correlationId?, userId (UUID), source (api-gateway | sync-engine | worker | ai-agents | system). createEvent auto-fills eventId/timestamp/version; parseLakshmiDomainEvent validates against the LakshmiDomainEventSchema union.

Event Types and Payloads#

The table below lists each event type and its key payload fields. Consumer services use these event types to trigger downstream work — for example, a transaction.created event triggers the categorization worker.

Event type Payload highlights
account.sync.completed connectionId, provider, accountsUpdated, transactionsSynced, syncDurationMs, balanceChanges[], errors[]
account.sync.error connectionId, provider, errorCode, errorMessage, requiresReauth
transaction.created / transaction.updated / transaction.deleted transactionId, accountId, amountCents, date, merchantName?, originalDescription, status, isRecurring, categoryCode?
transaction.categorized transactionId, previousCategoryCode?, newCategoryCode, categorizationMethod (ml_model | rule_based | user_override | plaid_provided), confidence (0–1), merchantId?, embeddingGenerated
budget.approaching / budget.exceeded / budget.reset budgetId, budgetCategoryId, categoryCode, allocatedCents, spentCents, remainingCents, spentPct, triggeringTransactionId?, period bounds
alert.triggered alertRuleId, alertEventId, alertType, severity (info/warning/critical), title, channels[], metadata
investment.rebalance.needed / investment.rebalance.completed portfolioId, accountId, maxDeviationPct, driftedAssetClasses[], estimatedTaxImpactCents?, recommendedTrades[]
tax.harvest.opportunity / tax.harvest.executed portfolioId, taxLotId, securityId, securityTicker, lossAmountCents (negative), estimatedTaxSavingsCents, replacementSecurityId?, washSaleWindowEnd, taxYear
credit.score.increased / credit.score.decreased / credit.score.updated bureau (equifax/experian/transunion), scoreModel, previousScore?, currentScore (300–850), changePts?, keyFactors[]
goal.milestone.reached / goal.completed / goal.at_risk / goal.off_track goalId, goalName, goalType, targetAmountCents, currentAmountCents, progressPct, targetDate?, projectedCompletionDate?, monthsAheadBehind?, milestoneThresholdPct?
ai.recommendation recommendationId, agentType, priority, title, summary, estimatedAnnualImpactCents?, actionableSteps[], expiresAt?, modelVersion

Kafka Topic Routing#

LAKSHMI_TOPICS resolves topic names from environment with defaults, allowing operators to override any topic name without a code change. The topic-to-event mapping is important: notably, both budget.* and credit.score.* events route to the shared lakshmi.alerts.triggered topic rather than domain-specific topics, keeping alert consumers simple.

Topics: lakshmi.accounts.sync, lakshmi.transactions.new, lakshmi.transactions.categorized, lakshmi.alerts.triggered, lakshmi.investments.rebalance, lakshmi.tax.harvest, lakshmi.goals.milestone, lakshmi.ai.recommendation. topicForEvent maps each event type to its topic.

Background Processing (BullMQ)#

Lakshmi's background pipeline uses BullMQ over ioredis (BullMQ requires dedicated connections). Jobs are organized into priority queues so that user-visible work (account sync) always runs before lower-priority work (report generation, data export). apps/lakshmi/worker/src/queues.ts defines the full pipeline.

Queues by Priority#

The following queues are defined in QUEUE_NAMES, ordered from highest to lowest priority. Each queue has a dead-letter queue (DLQ_NAMES, suffix :dlq) that receives jobs after all retry attempts are exhausted.

Queue Priority Job payload Retry policy
lakshmi:account-sync 1 (critical) AccountSyncJob 5 attempts, exponential backoff from 2 s
lakshmi:transaction-categorize 2 (high) TransactionCategorizeJob 4 attempts, exponential from 1 s
lakshmi:ai-recommendation 3 (medium) AiRecommendationJob 3 attempts, exponential from 5 s
lakshmi:report-generation 4 (low) ReportGenerationJob 3 attempts, fixed 30 s
lakshmi:data-export 5 (lowest) DataExportJob 2 attempts, fixed 60 s

attachDlqForwarder moves exhausted jobs into the DLQ with the original job data, failure timestamp, final error, and attempt count.

Job Payloads#

Each job type carries just enough context for the worker to execute the task without a round-trip to look up the work:

  • AccountSyncJobuserId, connectionId, provider (plaid | yodlee | mx | finicity | tink), syncFrom?, fullSync?. Deduplicated by job ID sync:{userId}:{connectionId}.
  • TransactionCategorizeJobuserId, transactionIds[], force?.
  • AiRecommendationJobuserId, domains[] (tax_harvest, roth_conversion, debt_payoff, budget_reallocation, goal_progress, credit_optimization, insurance_gap, retirement_contribution), householdId?. Deduplicated by recommend:{userId}.
  • ReportGenerationJobuserId, reportType (net_worth_summary, tax_year_summary, investment_performance, debt_payoff_progress, spending_analysis, budget_review, annual_review), period, format (pdf | csv | json), outputKey.
  • DataExportJobuserId, exportId, domains[], format (json | csv | zip), expiresAt. Deduplicated by export:{exportId}.

Repeatable Schedules#

apps/lakshmi/scheduler/src/schedules.ts registers BullMQ repeatable jobs that run on configurable cron patterns:

  • due-account-sync-sweep — syncs accounts whose refresh interval has elapsed.
  • uncategorized-transaction-sweep — picks up transactions that missed the real-time categorization path.
  • daily-ai-recommendations — generates daily AI recommendation batches.
  • daily-financial-report-rollups — builds daily summary aggregates.
  • expired-export-maintenance — cleans up export files past their TTL.

Persistence (@lakshmi/db)#

@lakshmi/db is the Drizzle ORM data layer over PostgreSQL. It declares 20 PostgreSQL namespaces (schema/namespaces.ts) and 78 tables (schema/*.ts). Understanding the persistence layer is essential for any feature that adds new data or modifies existing queries.

Connection Pooling (connection.ts)#

The connection pool is shared across all domain services using the same PostgreSQL database. Uses pg.Pool + drizzle-orm/node-postgres. The connection string comes from LAKSHMI_DATABASE_URL. Pool defaults: max 20, min 2 connections, 30 s idle timeout, 10 s acquisition timeout, 30 s statement timeout; application_name is lakshmi_service. getDb, getPool, getAllPoolStats, and closeAllConnections are the public connection API.

Namespaces#

The 20 PostgreSQL namespaces keep each domain's tables in their own schema, which makes RLS policies and migrations easier to manage:

accounts, transactions, budgets, investments, tax, debt, credit, retirement, insurance, estate, real_estate, crypto, income, goals, behavioral, household, business, alerts, audit (schema/namespaces.ts); plus shared reference tables in the schemas above.

Representative Tables#

The full schema covers 78 tables. The examples below highlight the most important tables and the non-obvious design choices engineers should be aware of.

  • household.lakshmi_usersid (UUID PK), externalAuthId (unique), email (unique), displayName, subscriptionTier (default free), onboardingStep, financialLiteracyLevel, riskTolerance, primaryCurrency, taxFilingStatus, notificationPreferences / privacySettings (JSONB), twoFactorEnabled, dataExportRequestedAt, deletedAt (soft delete). Unique indexes on email and externalAuthId.
  • household.lakshmi_households, lakshmi_household_members (RBAC capability flags canViewAllAccounts, canEditBudget, …; unique on (householdId, userId)), lakshmi_advisor_access (accessToken unique, mandatory expiresAt, allowedDataCategories[]).
  • accounts.lakshmi_institutions — per-provider IDs (plaidInstitutionId, yodleeProviderId, mxInstitutionCode, finicityInstitutionId, tinkFinancialInstitutionId), openBankingStandard (fdx/psd2/cdr).
  • accounts.lakshmi_provider_connections — encrypted accessToken / refreshToken / consentId, status, syncFrequencyMinutes (default 240), consecutiveSyncFailures, consent timestamps.
  • accounts.lakshmi_accountsaccountType (the lakshmi_account_type enum), balances in integer cents, annualPercentageRate / annualPercentageYield as numeric(8,5), flags (excludeFromNetWorth, isSharedWithHousehold, …), JSONB providerMetadata. Unique index on (connectionId, providerAccountId).
  • accounts.lakshmi_balance_snapshots and accounts.lakshmi_net_worth_history — TimescaleDB hypertables (see below).
  • transactions.lakshmi_transactionsamountCents (positive = credit, negative = debit), categoryId / userCategoryId, categorizationMethod (the lakshmi_categorization_method enum), categorizationConfidence (numeric(5,4)), location coordinates, behavioral/tax flags (isRecurring, isSubscription, isTaxDeductible, isSplit, …), tags[], splitParentId self-reference, JSONB providerRawData.
  • transactions.lakshmi_transaction_categories — hierarchical Plaid-style taxonomy (primaryCategory, detailedCategory, categoryCode unique, parentCategoryCode, isCustom).
  • transactions.lakshmi_transaction_embeddings — a pgvector vector(1536) column (model text-embedding-3-small) for similarity-based categorization; an ivfflat cosine index is created in migrations.
  • transactions.lakshmi_merchants, lakshmi_recurring_rules.
  • Domain tables follow the same per-namespace pattern, including budgets.* (4 tables), investments.* (6: portfolios, holdings, securities, tax lots, price history, market benchmarks), tax.* (7), debt.* (4), credit.* (5), retirement.* (5), insurance.* (4), estate.* (4), real_estate.*, crypto.* (5), income.* (4), goals.* (4), behavioral.* (4), business.* (4), and alerts.*.
  • alerts.lakshmi_alert_rulesconditions (JSONB), cooldownMinutes (default 60), maxPerDay (default 3), webhookUrl.
  • alerts.lakshmi_alert_eventscategory, severity, title/body, per-channel delivery timestamps (inAppDeliveredAt, pushDeliveredAt, emailDeliveredAt, smsDeliveredAt), isRead/isDismissed/isActioned, expiresAt.
  • audit.lakshmi_audit_logactionType, resourceType/resourceId, previousState/newState (JSONB), statusCode, correlationId, ipAddress, userAgent.
  • audit.lakshmi_data_access_logaccessorUserId, targetUserId, advisorAccessId, accessType, dataCategories[], request metadata.

TimescaleDB Hypertables#

Five time-series tables are converted to TimescaleDB hypertables by applyTimescaleHypertables. The chunk intervals and compression thresholds in TIMESCALE_HYPERTABLE_CONFIGS are tuned for Lakshmi's access patterns: short chunks for high-write tables (balance snapshots, 7 days), longer chunks for lower-write tables (price history, 30 days), and compression after data is unlikely to be updated.

Table Time column Segment-by Chunk interval Compress after
lakshmi_balance_snapshots snapshot_date user_id, account_id 7 days 90 days
lakshmi_net_worth_history snapshot_date user_id 30 days 90 days
lakshmi_security_price_history price_date security_id 30 days 365 days
lakshmi_market_benchmarks price_date benchmark_code 30 days 365 days
lakshmi_credit_score_history score_date user_id, bureau 90 days 180 days

Row-Level Security#

applyRowLevelSecurity provisions PostgreSQL RLS so every row is automatically scoped to the requesting user at the database layer, providing a defense-in-depth guarantee independent of application code. The current user is read from current_setting('app.current_user_id').

Policy builders: buildUserScopedRlsPolicy (direct user_id match), buildHouseholdSharedRlsPolicy, buildHouseholdOwnerRlsPolicy, buildHouseholdMembersRlsPolicy, and buildParentScopedRlsPolicy (rows scoped through a parent table). PARENT_SCOPED_RLS_CONFIGS lists the parent-scoped tables: lakshmi_transaction_embeddings, lakshmi_budget_categories, lakshmi_holdings, lakshmi_tax_lots.

Migrations and Reference Data#

migrations.ts provides runMigrations, migrateLakshmiUp, rollbackLakshmiLastBatch, rollbackLakshmiAll, getLakshmiMigrationStatus, and createLakshmiMigrationService. Migrations are tracked in public.lakshmi_schema_migrations under advisory lock 610001. migration-registry.ts registers LAKSHMI_MIGRATIONS — the LAKSHMI_INITIAL_SCHEMA_MIGRATION (full schema) and the LAKSHMI_MARKET_BENCHMARKS_MIGRATION — each with up/down SQL.

seed.ts (seedReferenceData) and seed-generators.ts load reference data that must be present before the application starts. Seed-data constants (seed-data/index.ts): PLAID_TRANSACTION_CATEGORIES, FEDERAL_TAX_BRACKETS_2024, STATE_TAX_BRACKETS_2024, SOCIAL_SECURITY_BENEFIT_TABLES, RMD_UNIFORM_LIFETIME_TABLE, IRS_CONTRIBUTION_LIMITS_2024, MARKET_BENCHMARKS, CREDIT_SCORE_FACTOR_WEIGHTINGS, INSURANCE_PRODUCT_TEMPLATES.

Shared PostgreSQL Enums#

schema/enums.ts declares the database-level pgEnum types (all prefixed lakshmi_). These enums are the canonical source of valid values at the database layer; the TypeScript types in @lakshmi/core mirror them but are maintained separately.

lakshmi_account_type (28 values), lakshmi_account_status, lakshmi_currency_code (26 currencies), lakshmi_subscription_tier, lakshmi_transaction_type, lakshmi_transaction_status, lakshmi_categorization_method, lakshmi_budget_type, lakshmi_budget_period, lakshmi_budget_status, lakshmi_security_type, lakshmi_asset_class, lakshmi_rebalancing_strategy, lakshmi_tax_filing_status, lakshmi_capital_gains_term, lakshmi_tax_lot_method, lakshmi_debt_type, lakshmi_payoff_strategy, lakshmi_credit_bureau, lakshmi_credit_score_model, lakshmi_insurance_policy_type, lakshmi_insurance_policy_status, lakshmi_property_type, lakshmi_property_purpose, lakshmi_crypto_network, lakshmi_defi_protocol_type, lakshmi_equity_grant_type, lakshmi_vesting_schedule_type, lakshmi_goal_type, lakshmi_goal_status, lakshmi_household_role, lakshmi_advisor_permission_level, lakshmi_business_entity_type, lakshmi_alert_category, lakshmi_alert_delivery_channel, lakshmi_alert_severity, lakshmi_risk_tolerance, lakshmi_aggregation_provider, lakshmi_document_type.

Note on enum surface: the database lakshmi_account_type enum (28 values, e.g. depository_checking, investment_401k_traditional) and the @lakshmi/core FinancialAccountType discriminated-union surface (32 type literals, e.g. checking, 401k) are independent encodings of the account-type concept defined in two separate packages. Mapping between them happens in the accounts/sync layer.

State Machines#

State machines encode the lifecycle of long-lived domain objects. Understanding these transitions is essential when debugging sync failures, goal tracking anomalies, or job pipeline stalls.

Connection Status#

AccountConnection.status (@lakshmi/core): the connection begins active.

  • From active it can move to degraded (partial sync), pending_mfa / pending_oauth (awaiting user authentication), disconnected (must re-authenticate), error (unrecoverable), or revoked (token revoked by institution or user).
  • The accounts sync engine drives a pending_mfa / disconnected connection back to active on a successful re-authentication.
  • The DB lakshmi_account_status enum (active, inactive, closed, error, pending_verification, requires_reconnect) is the persisted account-level status — distinct from the connection status.

Goal Status#

The DB lakshmi_goal_status enum tracks how a goal is progressing: not_started, in_progress, on_track, behind, at_risk, achieved, paused, abandoned. achieved and abandoned are terminal. The goal.* Kafka events (goal.milestone.reached, goal.completed, goal.at_risk, goal.off_track) are emitted as a goal advances. @lakshmi/goals carries its own GoalStatus working type used by MultiGoalEngine.

Onboarding#

OnboardingStep (@lakshmi/core) advances in order, with each step building on the previous: profilefinancial_profilelink_first_accountset_budgetset_goalexplore_insightscompleted. Steps may be skipped (skippedSteps).

Insurance Policy Status#

The DB lakshmi_insurance_policy_status enum: active, expired, cancelled, lapsed, pending, claim_in_progress.

Background Job Lifecycle#

A BullMQ job runs through BullMQ's activecompleted / failed states. On failed it is retried per the queue's attempts/backoff policy. A job that exhausts all attempts is forwarded by attachDlqForwarder into the queue's dead-letter queue as a terminal dlq_entry.

Invariants and Hard Requirements#

The following invariants are grounded in @lakshmi/core, @lakshmi/security, the public-API code, and features.md / architecture.md. Every piece of code in the domain must uphold these — they are not optional.

  1. Integer-cents money. All monetary fields in FinancialAccount, AccountBalance, and the DB schema are stored as integer cents (or the currency's minor unit); Money rejects non-integer amountMinor.
  2. No implicit cross-currency arithmetic. Money arithmetic throws a TypeError on a currency mismatch; conversion must go through ExchangeRate.
  3. Banker's rounding. Money division/multiplication and fromDecimal use round-half-to-even (bankersRound) to minimize aggregate bias.
  4. Branded IDs. Cross-entity references are compile-time protected by the Brand<T, B> pattern.
  5. Consent-first, revocable aggregation. Every integration requires explicit user consent before connection and is revocable; revocation moves the AccountConnection to revoked. AccountConnection.consentExpiresAt tracks PSD2/CDR consent expiry.
  6. Read-only crypto exchange links. @lakshmi/crypto's validateCryptoExchangeReadOnlyPermissions rejects exchange credentials that are not read-only.
  7. Encryption at rest, least privilege. Sensitive financial data is encrypted (@lakshmi/security EncryptionTier standard/sensitive/ critical); provider tokens are encrypted at the application layer before storage; PostgreSQL RLS scopes every row to the requesting user.
  8. Time-limited advisor access. AdvisorAccess.expiresAt and lakshmi_advisor_access.expiresAt are mandatory — advisor access is never indefinite — and every access is recorded in accessLog / audit.lakshmi_data_access_log.
  9. Corrected categories are pinned. A user category correction (categorizationMethod = user_override, userCategoryId) is treated as ground truth and is not re-categorized by the automated pipeline.
  10. Budget overage is warning-only. A budget overage emits a budget.exceeded alert and never blocks a transaction, unless a self-imposed cap or guardian/parental control explicitly escalates it.
  11. Explainable recommendations. AI recommendations carry confidence, model version, evidence, and actionable steps so any output is reproducible and auditable.
  12. Information vs. regulated advice. Tax, investment, credit, and insurance outputs separate general information from regulated advice; regulated advice is surfaced only where the product has the required compliance workflow.
  13. OAuth-scoped public API. Every public REST endpoint requires its declared OAuth scope; missing token → 401, missing scope → 403.
  14. Verification expectations. Every financial calculation, recommendation, aggregation, and alert path is expected to carry deterministic tests plus privacy, consent, audit, and contract tests; integration tests use sandbox fixtures and never require live credentials in CI (architecture.md).

Configuration and Environment Inputs#

The following environment variables configure the domain's services. All Kafka topic variables have sensible defaults and need only be set when the deployment uses non-default topic names.

Variable Consumer Purpose
LAKSHMI_DATABASE_URL @lakshmi/db (connection.ts, migrations.ts) PostgreSQL connection string
LAKSHMI_KAFKA_BROKERS api-gateway (kafka.ts) Comma-separated Kafka broker list (default localhost:29092)
LAKSHMI_TOPIC_ACCOUNTS_SYNC api-gateway (events.ts) Override for the accounts-sync topic
LAKSHMI_TOPIC_TRANSACTIONS_NEW api-gateway Override for the new-transactions topic
LAKSHMI_TOPIC_TRANSACTIONS_CATEGORIZED api-gateway Override for the categorized-transactions topic
LAKSHMI_TOPIC_ALERTS_TRIGGERED api-gateway Override for the alerts-triggered topic
LAKSHMI_TOPIC_INVESTMENTS_REBALANCE api-gateway Override for the rebalance topic
LAKSHMI_TOPIC_TAX_HARVEST api-gateway Override for the tax-harvest topic
LAKSHMI_TOPIC_GOALS_MILESTONE api-gateway Override for the goals-milestone topic
LAKSHMI_TOPIC_AI_RECOMMENDATION api-gateway Override for the AI-recommendation topic

A Redis URL is supplied programmatically to the BullMQ queue/worker factories (createQueues, createWorker). The public REST API config (PublicRestApiConfig) accepts publicBaseUrl, issuer, authorizationEndpoint, tokenEndpoint, and jwksUri overrides.

V2 Surfaces#

Lakshmi exposes two V2 adapter services under V2/services/*. Both are off-rollback and must never feed deterministic match simulation or competitive game outcomes. Active TypeScript packages now exist for both surfaces: @v2/lakshmi-responsible-play-spend-insight and @v2/per-account-vault-estate-bridge, each composing the corresponding @lakshmi/* domain libraries at workspace:* and pinning mayInfluenceRollback: false.

V2 Responsible-Play Spend Insight Contract#

@v2/lakshmi-responsible-play-spend-insight (apps/v2/lakshmi-responsible-play-spend-insight) is the V2 adapter for responsible-play store confirmation. It composes @lakshmi/behavioral, @lakshmi/budgeting, and @lakshmi/transactions. (The historical @lakshmi/spend-insight reference is not implemented and must not be built.)

The contract requires explicit player opt-in before any behavioral nudge, impulse-detection prompt, weekly-summary reflection, or self-imposed cap is applied. Parental controls are guardian policy and apply independently of the player's own opt-in. Budget overages remain warning-only unless a self-imposed cap or a parental control explicitly blocks the action or requires guardian approval. The adapter is off rollback: spend insight can affect store confirmation, guardian approval, player education, and weekly-summary copy, but it must never feed deterministic match simulation or competitive outcomes.

V2 Per-Account Vault Asset-Transfer Schema#

The V2 Per-Account Vault Asset-Transfer Schema is the reciprocal estate-transfer contract owned by Lakshmi and consumed by the V2 vault bridge. @v2/per-account-vault-estate-bridge (apps/v2/per-account-vault-estate-bridge) is the V2 adapter for per-account vault estate planning. It composes @lakshmi/estate with @oshun/identity account inheritance / delegation gates and @themis/transparency immutable transfer audit records.

The reciprocal Lakshmi schema is v2.per-account-vault-asset-transfer, which requires nine fields: vaultPlanId, householdId, ownerOshunAccountId, assetId, beneficiaryId, delegationId, evidenceDocumentId, transferInstructions, and themisAuditRecordId.

Lakshmi remains the source of truth for asset-inventory readiness, encrypted estate-document-vault completeness, beneficiary designations, digital-legacy action items, emergency-access readiness, and executor/trustee runbooks. V2 may publish an estate-transfer manifest only when all of the following hold:

  1. Each required asset transfer is marked ready by Lakshmi.
  2. The beneficiary tracker has no missing or conflicting designations.
  3. The delegation-evidence document exists in the encrypted estate-document vault.
  4. @oshun/identity validates the canonical owner account and sensitive-action gates.
  5. @themis/transparency records the delegation plus transfer execution in a valid hash chain with an anchored checkpoint.

This schema is an estate-administration control plane only. It is off rollback, server-authoritative, account/companion-only, and rejects live gameplay frame RPCs (the bridge guards every transfer call with a calledFromLiveGameplayFrame check). It must never feed deterministic match simulation, competitive frame outcomes, damage, AI, or rollback inputs.

Cross-Domain Boundaries#

Lakshmi's boundary with each adjacent domain is drawn around ownership of the financial decision, not raw data. Each boundary below exists for a specific architectural reason.

  • Maat owns enterprise finance, capital, and organizational operating systems; Lakshmi owns personal and household finance. The boundary prevents either domain from needing to understand the other's internal data model. Maat may consume aggregate business intelligence and risk where the user has permitted it.
  • Aje owns blockchain infrastructure and Web3 protocols and supplies the on-chain asset/provenance infrastructure consumed by @lakshmi/crypto. The boundary exists so that chain-level concerns (node access, transaction signing, protocol logic) live in one place rather than being re-implemented by every consumer.
  • Cybele owns real-estate and construction domain facts; @lakshmi/real- estate consumes that context but owns the personal-finance decision. This avoids duplicating property records, AVM models, and market data.
  • Themis owns governance policy and legal/procedural decision frameworks and supplies the immutable transfer audit records used by the V2 vault surface. Estate transfers are legal events; the audit chain must be maintained by a domain whose sole purpose is governance integrity.
  • Gaia (Phase 175, planned) supplies renewable-energy-potential and climate-risk products as inputs to Lakshmi for energy-trading support, household-capacity planning, insurance context, property-risk analysis, and financial-scenario modeling. Gaia owns forecast generation and uncertainty; Lakshmi owns the financial-advice boundary and the user-facing decision.
  • Freya, Asase, Brigid, Saraswati, and other commercial domains may expose user-permitted income, expense, asset, and business data through explicit contracts.

Technology Stack#

Lakshmi's technology choices are listed here for quick orientation. Source of truth is libs/lakshmi/README.md and the service source files.

  • TypeScript on Node.js — all 24 libraries and 6 services.
  • PostgreSQL with pgvector (embedding similarity for ML categorization) and TimescaleDB (time-series storage for balances, prices, credit scores).
  • Redis — caching, real-time balance tracking, rate limiting, sessions.
  • Kafka via kafkajs — domain-event streaming from the api-gateway.
  • BullMQ over ioredis — background job processing.
  • Hono — API gateway HTTP/WebSocket server.
  • Drizzle ORM — type-safe SQL and migrations.
  • Zod — runtime validation at API boundaries and in domain types.
  • MinIO S3 — document storage for receipts, tax documents, estate files.
  • WebSockets — real-time dashboard updates and alerts.