# Lakshmi Domain — Technical Specifications

## 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`.
- **`AccountSign`** — `asset` 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`).
- **`AccountConnection`** — `id: ConnectionId`, `userId`, `institutionId`,
  `provider: AggregationProvider`, `providerItemId?`, `accessTokenRef?`,
  `status: ConnectionStatus`, sync timestamps, `error?: ConnectionError`,
  `linkedAccountCount`, `consentExpiresAt?` (PSD2/CDR), `webhooksEnabled`,
  `supportsHistoricalBackfill`, `earliestTransactionDate?`.
- **`ConnectionError`** — `code`, `message`, `userActionRequired`,
  `suggestedAction?`, `firstOccurredAt`, `consecutiveFailures`.
- **`Institution`** — `id: 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.

- **`AggregationProvider`** — `plaid`, `yodlee`, `mx`, `finicity`, `tink`,
  `manual`.
- **`ConnectionStatus`** — `active` (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.

- **`SubscriptionTier`** — `free`, `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.
- **`AuthMetadata`** — `oshunUid`, `email`, `emailVerified`, `phoneNumber?`,
  `phoneVerified`, `mfaMethods` (array of `totp` | `sms` | `backup_codes`),
  `lastLoginAt?`, `failedLoginAttempts`, `lastFailedLoginAt?`, `lockedUntil?`.
- **`NotificationChannel`** — `push`, `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`.
- **`PrivacySettings`** — `allowAggregateAnalytics`, `allowModelTraining`,
  `allowPeerBenchmarking`, `shareWithHousehold`, `dataRetentionMonths?`, and a
  GDPR/CCPA `consent` record (`version`, `grantedAt`, `ipAddress`).
- **`OnboardingStep`** — `profile`, `financial_profile`, `link_first_account`,
  `set_budget`, `set_goal`, `explore_insights`, `completed`.
  **`OnboardingState`** tracks `currentStep`, `completedSteps`,
  `profileCompleteness` (0–100), `startedAt`, `completedAt?`, `skippedSteps`.
- **`FinancialProfileSummary`** — `netWorthCents`, `monthlyGrossIncomeCents`,
  `monthlySavingsRate`, `totalDebtCents`, `emergencyFundMonths`,
  `primaryCreditScore?`, `estimatedEffectiveTaxRate?`, `asOfDate`.
- **`LakshmiUser`** — `id: UserId`, `auth: AuthMetadata`, `name`,
  `dateOfBirth?`, `residence` (`stateCode`/`country`/`timezone`), `tier`,
  `billing` (`status` ∈ `active` | `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.

- **`HouseholdMemberRole`** — `owner`, `admin`, `member`, `viewer`, `child`.
- **`HouseholdMember`** — `userId`, `role`, `joinedAt`, `sharedAccountIds`,
  `accountVisibility` (`full` | `summary_only` | `hidden`), `status` (`active` |
  `pending_invite` | `revoked`), `inviteEmail?`, `invitedAt?`,
  `inviteExpiresAt?`.
- **`HouseholdAccountDesignation`** — `individual`, `shared`, `hidden`,
  `managed_child`. **`HouseholdSharedAccountDesignation`** binds an account to a
  designation, `visibleToRoles`, and `transactionVisibility` (`full` |
  `category_summary` | `balance_only` | `hidden`).
- **`JointBudgetConfig`** — `jointCategories`, `splitCategories` (Plaid PFC
  codes), `splitRatio`.
- **`Household`** — `id: 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.

- **`TaxFilingStatus`** — `single`, `married_filing_jointly`,
  `married_filing_separately`, `head_of_household`,
  `qualifying_surviving_spouse`.
- **`EmploymentType`** — `w2_employee`, `self_employed_sole_proprietor`,
  `self_employed_s_corp`, `self_employed_c_corp`, `self_employed_llc`,
  `contractor_1099`, `partnership`, `retired`, `student`, `unemployed`, `other`.
- **`FinancialLiteracyLevel`** — `beginner`, `intermediate`, `advanced`,
  `expert`.
- **`IncomeBracket`** — `under_30k`, `30k_50k`, `50k_75k`, `75k_100k`,
  `100k_150k`, `150k_200k`, `200k_500k`, `over_500k`.
- **`RiskToleranceProfile`** — `score` (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`.
- **`FinancialProfile`** — `userId`, `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.

- **`AdvisorPermissionScope`** — `accounts: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`.
- **`AdvisorAccess`** — `id: 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 `ReviewQueueItem`s. `PersonalizationEngine` learns from
`CorrectionEvent`s into a `UserPersonalizationProfile`. `CustomRulesEngine`
evaluates user `CustomRule`s — conditions on merchant name, description, amount,
account, or date pattern; actions include `SetCategoryAction`, `AddTagsAction`,
`SetSplitAction`, and `AssociateGoalAction`. `MultiLabelCategorizer` splits a
transaction across multiple `CategoryAllocation`s.

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

- `RecurringTransactionDetector` — emits `RecurringPattern`s
  (`RecurringFrequency`, `RecurringType`, `RecurringConfidence`).
- `SubscriptionManager` — tracks `SubscriptionRecord`s, `PriceChangeEvent`s,
  `FreeTrialEvent`s, 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 `SplitPart`s
  (`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 `ScenarioDefinition`s 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 scoring** — `CompositeFinancialHealthScorer` /
  `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 stress** — `FinancialStressIndexDetector` /
  `detectFinancialStress` produce a `FinancialStressIndexResult`
  (`FinancialStressLevel`, `FinancialStressSignal`,
  `FinancialStressInterventionTrigger`).
- **Lifestyle inflation** — `LifestyleInflationDetector` analyzes income-rise
  events and category drivers (`LifestyleInflationSeverity`,
  `LifestyleInflationNudge`).
- **Resilience** — `FinancialResilienceScorer` (`FinancialResilienceLevel`,
  `FinancialResilienceShockCapacity`).
- **Spending behavior** — `SpendingBehaviorPatternAnalyzer` detects
  `EmotionalSpendingTrigger`, `PaydaySplurgePattern`, `TimePattern`,
  `DayOfWeekPattern`, `MerchantAffinityCluster`.
- **Impulse detection** — `ImpulsePurchaseDetector` / `detectImpulsePurchase`
  produce an `ImpulsePurchaseDetectionResult` with `ImpulsePurchaseCandidate`s,
  `ImpulsePurchaseSeverity`, `ImpulseBudgetImpact`/`ImpulseGoalImpact`, and an
  `ImpulseReflectionPrompt`.
- **Nudges** — `FinancialNudgeEngine` / `generateFinancialNudges` produce
  `FinancialNudge`s with `FinancialNudgeType`, `FinancialNudgeSeverity`,
  `FinancialNudgeTone`, `FinancialNudgeEvidence`, and a
  `FinancialNudgeActionPayload`.
- **Smart defaults & savings automation** — `SmartDefaultConfigurationEngine`
  and `SmartSavingsAutomationEngine` (round-up, percentage-of-income,
  surplus-sweep, windfall rules; `SmartSavingsTransferInstruction`).
- **Loss-aversion protection** — `LossAversionProtectionEngine` surfaces
  `LossAversionIntervention`s using historical drawdown-recovery samples.
- **Habits, badges, challenges** — `FinancialHabitStreakTracker`,
  `LakshmiAchievementBadgeSystem` (`LAKSHMI_BADGE_CATALOG`),
  `FinancialChallengeSystem` (`LAKSHMI_FINANCIAL_CHALLENGE_TEMPLATES`).
- **Peer benchmarking** — `PeerBenchmarkingEngine` /
  `compareAgainstAnonymousPeers` compare against an anonymous cohort
  (`PeerBenchmarkSegment`, `PeerBenchmarkMetricType`).
- **Weekly reflection** — `WeeklyFinancialReflectionEngine` /
  `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/`.

- **Portfolio** — `PortfolioAggregationEngine`, `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`.
- **Performance** — `computeTWR`, `computeMWR`, `computeXIRR`;
  `BenchmarkComparisonEngine` with `BENCHMARK_DEFINITIONS`. Types include
  `DailyValuation`, `CashFlow`, `LookbackPeriod`, `TWRResult`, `MWRResult`,
  `XIRRResult`, `BenchmarkComparison`, `PerformanceAttribution`,
  `BHBAttributionEffect`.
- **Risk** — `RiskMetricsEngine`, `VaREngine`; types `RiskMetrics`,
  `DrawdownAnalysis`, `CorrelationMatrix`, `VaRMethod`, `ConfidenceLevel`,
  `VaRResult`, `VaRSuite`.
- **Advanced** — `FactorAnalysisEngine`, `FeeImpactAnalyzer`,
  `ExposureAnalyzer`, `DividendIntelligenceEngine`,
  `FixedIncomeAnalyticsEngine`, `OptionsTracker`, `ESGScoringEngine`,
  `AlternativeInvestmentTracker`, `ConcentratedStockAnalyzer`, `IPSGenerator`.
- **Rebalancing** — `RebalancingEngine`, `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/debt`** — `PACKAGE_NAME = '@lakshmi/debt'`; modules `inventory/`,
`payoff/`, `refinancing/`. Computes amortization, compares avalanche/snowball/
hybrid payoff strategies, and evaluates refinancing.

**`@lakshmi/credit`** — `PACKAGE_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 `FinancialAdvisorRecommendation`s 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.

- **`EncryptionTier`** — `standard`, `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.

- **`LakshmiRbacRole`** — `owner`, `admin`, `member`, `viewer`, `child`,
  `advisor`.
- **`LakshmiDataCategory`** — finance data-category enum gating access.
- **`LakshmiAccessAction`** — `view`, `edit`, `export`, `share`.
- **`LakshmiAccountVisibility`** — `private`, `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`
- **Endpoints** — `authorization_endpoint: /oauth2/authorize`,
  `token_endpoint: /oauth2/token`, `jwks_uri: /.well-known/jwks.json`
- **Supported flows** — `response_types_supported: ['code']`;
  `grant_types_supported: ['authorization_code', 'refresh_token', 'client_credentials']`
- **PKCE** — `code_challenge_methods_supported: ['S256']`
- **Client auth** —
  `token_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:

- **`AccountSyncJob`** — `userId`, `connectionId`, `provider` (`plaid` |
  `yodlee` | `mx` | `finicity` | `tink`), `syncFrom?`, `fullSync?`. Deduplicated
  by job ID `sync:{userId}:{connectionId}`.
- **`TransactionCategorizeJob`** — `userId`, `transactionIds[]`, `force?`.
- **`AiRecommendationJob`** — `userId`, `domains[]` (`tax_harvest`,
  `roth_conversion`, `debt_payoff`, `budget_reallocation`, `goal_progress`,
  `credit_optimization`, `insurance_gap`, `retirement_contribution`),
  `householdId?`. Deduplicated by `recommend:{userId}`.
- **`ReportGenerationJob`** — `userId`, `reportType` (`net_worth_summary`,
  `tax_year_summary`, `investment_performance`, `debt_payoff_progress`,
  `spending_analysis`, `budget_review`, `annual_review`), `period`, `format`
  (`pdf` | `csv` | `json`), `outputKey`.
- **`DataExportJob`** — `userId`, `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_users`** — `id` (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_accounts`** — `accountType` (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_transactions`** — `amountCents` (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_rules`** — `conditions` (JSONB), `cooldownMinutes`
  (default 60), `maxPerDay` (default 3), `webhookUrl`.
- **`alerts.lakshmi_alert_events`** — `category`, `severity`, `title`/`body`,
  per-channel delivery timestamps (`inAppDeliveredAt`, `pushDeliveredAt`,
  `emailDeliveredAt`, `smsDeliveredAt`), `isRead`/`isDismissed`/`isActioned`,
  `expiresAt`.
- **`audit.lakshmi_audit_log`** — `actionType`, `resourceType`/`resourceId`,
  `previousState`/`newState` (JSONB), `statusCode`, `correlationId`,
  `ipAddress`, `userAgent`.
- **`audit.lakshmi_data_access_log`** — `accessorUserId`, `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: `profile` → `financial_profile` → `link_first_account` →
`set_budget` → `set_goal` → `explore_insights` → `completed`. 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 `active` → `completed` / `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.
