docs/fire-plan.md
reservation_percent / countable_percent /
funding_role model with one absolute share_percent per (goal, account).100% shares for eligible accounts at
goal creation.planner_mode (fire / traditional) and keep Monte Carlo output shape
unchanged in this refactor.goals_allocation becomes the canonical share table with:
idgoal_idaccount_idshare_percent REAL NOT NULLtax_bucket TEXT NULLcreated_atupdated_atpercent_allocationfunding_rolereservation_percentcountable_percentgoals_allocation.
(goal_id, account_id) index.GoalFundingRule { id, goalId, accountId, sharePercent, taxBucket?, createdAt, updatedAt }GoalFundingRuleInput { accountId, sharePercent, taxBucket? }taxBucket only as a retirement concern.
null.GoalPlan, SaveGoalPlan, and PlannerMode as-is.GoalService::new(...) so the core service has access to
AccountServiceTrait.
goal_value = account_value * share_percent / 100retirement_portfolio = sum(retirement shares only)activeachieved, archivedrefresh_goal_summary for a retirement goal without a saved plan should
still compute current value from shares.tax.taxableWithdrawalRate.RetirementTimingMode end-to-end.
share_percent must be within [0, 100].<= 100.
accountId entries in a single save payload.100% shares for every eligible
account.
is_active = true, is_archived = false, account_type in
SECURITIES | CASH | CRYPTOCURRENCY0 until shares are added.validate_retirement_plan must reject duplicate linkedAccountId values
across DC streams.save_goal_plan must reject linking a DC stream to an account that already
has participating goal shares.save_goal_funding must reject saving shares on any account already linked
by the retirement plan.Share % input per selected accountTax bucket selector per selected accountShare % input per selected accounttaxBucket,
earlyWithdrawalPenaltyRate, and earlyWithdrawalPenaltyAgeannualWithdrawal.YearlySnapshot and downstream deterministic trajectory DTOs should expose:
plannedExpensesfundedExpensesannualShortfallannualIncomegrossPortfolioWithdrawalnetWithdrawalFromPortfolioannualTaxesfundedExpenses + income as “expenses”.goals_allocation.sharePercent.AccountServiceTrait into GoalService and add atomic
retirement-goal auto-seeding.goals_allocation rows round-trip with share_percent70% retirement + 30% home on one account yields exact 70/3070% retirement + 30% home + 10% car is rejected100% for eligible active non-archived accounts0plannedExpenses - fundedExpenses == annualShortfallcargo checkcargo test -p wealthfolio-corepnpm type-checkfrom/to dates and no
targetDate-driven share expiry.taxBucket is authoritative for engine math; wrapper/country presets only
prefill values.SECURITIES, CASH, CRYPTOCURRENCY.