Checklist

Wealth-App Edge-Case Test Coverage Audit Checklist

Published May 8, 2026

Most production incidents in wealth-tech have the same shape: 'feature worked great in testing, then customer X did something unusual.' The fix takes 30 minutes. The customer-trust hit and rollback take a week. Almost every one of these 'unusual customer' cases is structurally enumerable — there is a finite, knowable set of edge-case archetypes the corpus should cover before a feature ships. This checklist is the audit. Walk through the items; any one that's missing from your corpus is a guaranteed future incident.

0 / 27 complete0%

Demographic & identity edge cases

  • ITIN filers (no SSN)

    Households with at least one member filing under an ITIN rather than SSN. Backend validators that hard-fail on non-SSN tax IDs reject these customers at onboarding silently.

    demographics.tax_id_type == 'ITIN'
  • Visa holders (H-1B, L-1, O-1)

    Non-citizen households with documented visa status. Drives FBAR / FATCA edge cases and tax-treaty applicability that pure-citizen test data never exercises.

    demographics.visa_status
  • Dual citizens

    Households with at least one dual citizen. Estate-planning and FATCA reporting paths only fire when this flag is true.

    demographics.dual_citizen == true
  • Multi-state residents

    Households whose tax residency is split across states (NY/NJ commuter, CA/NV partial-year, FL/NY snowbird). Multi-state tax allocation is a frequent source of tax-engine bugs.

    demographics.tax_residency.states[]
  • Cognitive decline / heightened-supervision flags

    Senior clients with documented cognitive-decline flags requiring heightened supervision per FINRA Rule 4512. Drives different recommendation, communication, and approval paths.

    members[].cognitive_status

Account & ownership structures

  • Joint accounts with non-equal ownership

    Joint accounts where ownership isn't 50/50 — JTWROS with explicit allocation, tenants in common with documented shares. Rebalancing and reporting that assumes 50/50 produces wrong cost basis allocation.

    accounts[].ownership_type == 'TIC' || .ownership_pct != 0.5
  • Trust-owned accounts (revocable + irrevocable)

    Accounts owned by revocable living trusts and irrevocable trusts, including grantor trusts and non-grantor trusts. Trust-account workflows must distinguish these because tax treatment differs materially.

    accounts[].owner_type == 'trust', .trust_type
  • Entity-owned accounts (LLC, partnership, corporation)

    Brokerage and operating accounts owned by entities. Beneficial-ownership documentation per FinCEN CDD must be present. Entity-account features tend to be afterthoughts.

    accounts[].owner_type == 'entity', .beneficial_owners[]
  • UTMA / UGMA custodial accounts

    Custodial accounts with the minor's age and state-specific age-of-majority. Transition-of-control workflows must handle these.

    accounts[].account_type == 'UTMA' || 'UGMA'
  • Self-directed brokerage windows in DC plans

    401(k) accounts with SDBA where individual securities are held alongside the core menu. Reporting that can't distinguish core-menu from SDBA holdings produces wrong allocation views.

    accounts[].plan_features.sdba == true

Transaction & holding edge cases

  • Wash-sale conflicts across accounts

    Holdings where harvesting in account A would trigger a wash sale because the spouse's IRA bought the same security 20 days ago. ~6% of would-be-harvestable lots in a real-world investor account.

    lots[].cross_account_wash_sale_conflict == true
  • QSBS-eligible positions

    §1202 qualified small business stock holdings with the holding-period and gross-asset-test attestation. Algorithms that don't recognize QSBS can recommend selling-for-loss against a 23.8% federal exclusion.

    lots[].qsbs_eligible == true
  • Restricted stock with vesting cliffs

    RSU / ISO / NSO grants with vesting schedules including cliffs. Vesting events drive AMT, ordinary income, and basis creation — algorithms that lose the vesting schedule produce wrong tax projections.

    equity_grants[].vesting_schedule
  • Fractional shares

    Holdings where share counts aren't integers. Reporting and tax-lot accounting that assumes integers off-by-pennies the totals.

    lots[].shares % 1 != 0
  • Negative cash balances (margin)

    Accounts with margin debit balances. Net-worth calculations that miss the margin liability produce inflated net-worth figures.

    accounts[].cash_balance < 0
  • Multi-currency holdings

    Holdings denominated in non-USD currencies (international clients, expats). FX-snapshot logic must be present and consistent.

    lots[].currency != 'USD'
  • Crypto / DeFi positions with cost-basis history

    Crypto holdings with the full receipt history (every airdrop, swap, staking reward is a basis event). Form 1099-DA-relevant.

    crypto_holdings[].receipt_history[]

Life-event & longitudinal edge cases

  • Mid-window divorces with QDRO

    Households with a divorce event in the longitudinal window plus the QDRO splitting retirement assets. Continuity bugs (assets reverting to the marital state in later snapshots) hide here.

    events[].type == 'divorce', qdro_present == true
  • Death of spouse with surviving-spouse trajectory

    Households crossing into surviving-spouse state with single-filer brackets, lost SS benefit, and step-up basis events. Many planning engines silently treat survivors as pre-death joint filers.

    events[].type == 'spouse_death'
  • Job loss with COBRA + IRA rollover

    Job loss in the window with subsequent COBRA period, rollover decisions, and unemployment income. Cash-flow models that flat-line through job loss are off by 30%+ for a year.

    events[].type == 'job_loss'
  • Immigration / emigration mid-window

    Becoming-a-resident or expatriating during the window. Tax-residency transition has knock-on effects through the longitudinal window.

    events[].type == 'residency_change'
  • RMD age crossing (73, 75)

    Households crossing the SECURE 2.0 RMD age during the window. RMD start year, amount, and tax impact must propagate forward correctly.

    events[].type == 'rmd_start'

Tax-scenario edge cases

  • AMT-binding households

    Households where the AMT actually binds (typically high-state-tax + ISO exercises + private-activity bond interest). AMT logic that's never exercised silently breaks.

    tax.amt_liability > tax.regular_liability
  • QBI / pass-through with complex K-1s

    K-1 recipients with QBI, SSTB classification, and W-2 wage limits. The QBI deduction has many edge cases that produce zero-deduction outcomes algorithms tend to miss.

    income.k1_complex == true
  • Net Investment Income Tax (NIIT) thresholds

    Households just above and just below the NIIT MAGI threshold. Threshold-cliff bugs produce wrong tax projections by exactly 3.8% at the cliff.

    tax.niit_applicable
  • Roth conversion + IRMAA tier interaction

    Households with planned Roth conversions where the conversion crosses an IRMAA tier two years out. Engines that handle conversion-year only miss the lookback.

    planning.roth_conversion_irmaa_impact
  • State-tax differential scenarios (e.g. CA → FL)

    Move-from-high-tax-state-to-no-tax-state scenarios in the window. Source-state tax claims to former residents are an enforcement-active area.

    events[].type == 'state_tax_residency_change'

Key takeaways

  • Most production incidents trace back to an edge-case archetype that wasn't in the test corpus. The set is structurally enumerable — having a checklist of these is preventive QA.
  • The cross-account / cross-product / multi-state edge cases are the most frequent source of incidents because they live in the integration seams between modules.
  • Life-event longitudinal continuity (divorce, death, job loss, residency change) is where 'feature works in fixture, fails in production' bugs cluster. Single-snapshot fixtures can't catch these.
  • Tax edge cases (AMT binding, QBI complexity, NIIT cliffs, IRMAA lookback) are the highest-leverage to add — each represents a structurally different code path that's easy to forget exists.