8000 GitHub - hrithiksaini99/MyFinances: MyFinances is a client-side personal finance tracking application with strong security practices. This document outlines the security measures implemented and best practices for deployment and usage. · GitHub
[go: up one dir, main page]

Skip to content

About

MyFinances is a client-side personal finance tracking application with strong security practices. This document outlines the security measures implemented and best practices for deployment and usage.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

MyFinances

CI CodeQL Copilot Docker Release

A modern, privacy-first web app to track accounts, debts, income, and spending, helping you plan and visualize your path to financial freedom.

All calculations happen locally in your browser — no accounts required. An optional self-hosted Node.js + PostgreSQL backend is available for multi-device sync (see DEPLOYMENT.md).

Security Status: ✅ Production-Ready | Risk Level: LOW | Audit Date: August 31, 2026 | Last Scan: Static security scan passed (0 HIGH, 0 MEDIUM)


🚀 Quick Start

# Development (Python)
python -m http.server 32900

# Docker (recommended for consistent environments)
docker compose up -d        # Build and run at http://localhost:32900
docker compose down         # Stop

# Open browser
http://localhost:32900

# Run tests
pytest tests/ -v                  # Run all tests
pytest tests/security/ -v         # Security tests only
pytest tests/features/ -v         # Feature tests only
pytest tests/ui/ -v               # UI/UX tests only
pytest tests/integration/ -v      # End-to-end tests only
pytest -m "not slow" -v           # Skip slow tests

See tests/README.md for comprehensive test documentation.
See CHANGELOG.md for version history and release notes.
For production deployment, see DEPLOYMENT.md.


🔒 Security & Privacy

MyFinances prioritizes your financial data security:

Security Features

  • ✅ Zero Data Transmission — All data stays on your device
  • ✅ XSS Prevention — All user input sanitized and HTML-encoded via escapeHtml()
  • ✅ Strong CSP — script-src 'self' https://cdn.jsdelivr.net, style-src 'self' — no inline scripts or styles (plus googletagmanager.com/google-analytics.com, allow-listed for the opt-in analytics feature below but never contacted unless you configure it)
  • ✅ Security Headers — X-Content-Type-Options, X-Frame-Options, frame-ancestors protection
  • ✅ No External Dependencies — Vanilla JavaScript (no npm supply-chain risk)
  • ✅ Secure File Imports — JSON validation + 2 MB size limit + full re-sanitization on import
  • ✅ Input Validation — Numeric bounds, date validation, text sanitization at every entry point
  • ✅ Client-Side Only (default) — No server, no authentication surface
  • ✅ Optional Postgres Backend — argon2id password hashing, server-side sessions (opaque token), httpOnly/Secure/SameSite=Strict cookies, CSRF double-submit tokens on every mutating request, NIST-style new-password rules with an optional Have I Been Pwned breach check, and a Settings → Security change-password form

Continuous Security Scanning

The CI pipeline runs five automated scans on every push and pull request to main:

  • CodeQL — GitHub SAST engine; detects XSS, injection, and logic bugs in src/ JavaScript
  • Trivy — Docker image — Gates on fixable CRITICAL/HIGH CVEs in the published container image
  • Trivy — Filesystem — Scans repo lockfiles and source for known-vulnerable packages and leaked secrets; gates on CRITICAL/HIGH
  • Trivy — IaC — Scans Dockerfile and docker-compose.yml for CIS-benchmark misconfigurations (informational)
  • Dependency Review — Blocks PRs that introduce new dependencies with HIGH or CRITICAL severity CVEs

All findings feed into the GitHub Security tab as SARIF reports.

Privacy Guarantee

  • ✅ All calculations run entirely in your browser
  • ✅ No data is sent to any server
  • ✅ No accounts, no tracking, no analytics by default — self-hosters can opt their own instance into Google Analytics via an env var (see DEPLOYMENT.md); nothing is ever sent to Google unless you configure it
  • ✅ Data stored only in your browser's localStorage (same-origin isolated)

Documentation


📋 Features

Navigation & Accessibility

  • Grouped main navigation — Three labeled groups: Overview (Health, Accounts, Income), Manage (Liabilities, Recurring, Savings, Plan), Analyze (Reports, Ledger, Reconcile, Retirement); active-group highlighting, aria-current, hamburger menu on ≤768px
  • Command palette — Ctrl/Cmd+K or the 🔍 toolbar button opens a fuzzy-search jump list across all 11 pages and common actions; Arrow-key navigation, Enter to activate, Escape restores focus; full role="dialog" / role="listbox" ARIA semantics
  • Theme selector (Light / Dark / High Contrast) — 3-way selector in the Settings modal (gear icon); preference persisted to localStorage. High Contrast targets WCAG AA/AAA with pure black surfaces, bright accent colors, and a bold focus outline on every interactive element; command palette includes a "Cycle theme" action
  • Print / Save as PDF — 🖨️ Print button on every page; @media print hides forms/controls so only read-only data content prints; browser print-to-PDF doubles as a PDF export
  • Keyboard navigation — all interactive elements reachable by keyboard; modals trap focus and Escape-to-close; calendar day-cells keyboard-activatable
  • Accessible control names — every button/tab has an accessible name; per-item Edit/Delete/Save/Cancel buttons name the item (e.g. Delete Visa card), toggle chips expose aria-pressed, and sortable column headers expose aria-sort plus a direction-aware label (#331); enforced by tests/ui/test_aria_labels.py
  • Reduced motion — prefers-reduced-motion: reduce collapses all CSS transitions/animations; Chart.defaults.animation disabled app-wide when the OS preference is set
  • Screen-reader chart tables — every Chart.js canvas has a paired visually-hidden .sr-only <table> with the same data, rebuilt on every chart re-render via renderChartDataTable() in utils.js
  • localStorage quota monitoring — soft-warning banner when usage crosses ~80% of the estimated 5 MB limit; hard-failure banner if setItem actually throws
  • In-app guide — the ❓ Help button opens guide.html in a new tab; theme (including High Contrast) follows the main app preference
  • $0 ledger amount policy — Settings → Advanced lets you Allow, Warn about, or Block $0 amounts in ledger overrides and recurring templates (transfers always need more than $0)
  • Language support (English / Español / Polski) — switch languages from the Settings modal (gear icon). Every page, pop-up and chart is translated, including Ledger-generated transaction names, and number/date formatting follows the selected language. Changing the language re-renders the page you're on.

Financial Health Dashboard

The app's default landing page — six at-a-glance metric cards:

Card What it shows
Debt-to-Income Ratio Monthly debt payments ÷ income; Healthy / Moderate / High Risk badge
Savings Rate Emergency + sinking fund contributions as % of income; Strong / Moderate / Low badge
Emergency Fund Runway Months of expenses covered per fund; Critical → Excellent badge
Debt Payoff Timeline Years to debt-free at minimum payments (avalanche); % progress bar
Monthly Cash Flow Income minus all outflows; Surplus / Break Even / Deficit badge with breakdown
Credit Utilization Card balances ÷ credit limits, per person and per card; an expandable "What affects your credit?" explainer covers the five common credit factors, with a status line where the app has data and a link to AnnualCreditReport.com — education only, never a score
Budget Allocation Bill + expense categories as % of income with colour-coded bars; debt payments row included

Internal links on each card navigate directly to the relevant page (Savings, Liabilities, Plan).


Account Management

  • Account types — Checking, Savings, Cash, Investment, Credit Card, Loan, or Other; name, starting balance, and optional interest rate (% APY)
  • Interest income — optional per-account interest rate (% APY); auto-generates a monthly Interest deposit in the Ledger (last day of month, APY ÷ 12 on projected end-of-month balance, compounding), overridable with the true posted amount
  • Account linking — income sources, one-time entries (bonuses/deposits), debts, recurring templates, and expense budgets can all be linked to an account
  • Account notes — optional free-text notes (up to 500 characters, multi-line) on each account, e.g. an institution phone number or why a starting balance is unusual. Cards show the first line; expand to read the whole note.
  • Projected monthly balance — each account card shows a projected end-of-month balance: starting balance ± all linked income, debt payments, recurring transactions, and expenses for the current month, including any ledger amount overrides
  • Net worth widget — current net worth and change from the prior snapshot shown on the Accounts page
  • Export / Import — accounts are included in the JSON backup (format version "4.0.0")

Debt Management

  • Unlimited debts — credit cards (revolving balance + APR) or fixed-amount recurring payments (subscriptions, rent, instalments)
  • Single-page add & manage — add form and debt list side by side; no page switching
  • Inline editing — Edit button populates the form for editing; list updates immediately on save
  • Update Balance — record a new balance for any credit card while preserving the original for progress tracking
  • Category labels — tag debts and filter the list by category
  • Priority levels — assign 1–100 priority for custom strategy ordering
  • Payoff Date display — every debt card shows a 📅 Payoff Date sourced from the plan calculation; shows "Run a plan to see" hint until a plan exists
  • Interest Paid to Date — estimate shown on each debt card, based on original balance and opened date
  • Payoff Analysis badge — each credit-card debt card shows a break-even comparison: your plan payment vs. minimum-only, with months saved and interest saved; no-plan state shows minimum-only estimate with a clear banner; toggle between Fixed and % of Balance minimum-payment mode
  • Accelerate modal — "Accelerate this debt →" button opens a live-preview modal: type an extra monthly payment and instantly see updated payoff date and interest saved; "Apply to Plan" wires the total into the Strategy page

Income Tracking

  • Income sources — name, amount per paycheck, first pay date, and frequency (bi-weekly or monthly); automatic pay-schedule projection for the current month
  • One-time entries — bonus, tax refund, cash deposit, check deposit, or other; linkable to an account
  • Monthly summary — expected income this month, regular pay, one-time entries, estimated annual total
  • Debt-to-income ratio — Plan page shows monthly debt payment as a % of income with a warning above 40%

Budget Tracking (Expenses)

  • Expense budgets — variable monthly spending targets with date tracking (for calendar and ledger); inline editing in the list
  • Bills — fixed monthly costs with due day and category (data model; no standalone add UI — use Recurring Templates for new fixed costs)
  • Cash Flow Summary — live panel: Income − Debt minimums − Bills − Budgeted expenses = Net remaining
  • Persisted to storage — expenses and bills are saved to localStorage and included in JSON export/import

Recurring Transaction Templates

  • Three types — Subscription (outflow), Reimbursement (inflow), Transfer (debit one account, credit another; both Ledger legs are marked ⇄, like one-off transfers)
  • Flexible frequency — Weekly, bi-weekly, monthly, quarterly, yearly
  • Start and end dates — constrain to a specific date range
  • Pause & skip controls — temporarily pause a template or skip individual months without deleting
  • Mark as Paid — confirm each of the month's payments and its actual amount; this marks the matching Ledger transaction Cleared and a different amount becomes its Ledger amount. Checking Cleared in the Ledger marks it paid here too (issue #434). Distinct from Skip; resets each calendar month
  • Integrated — recurring templates generate projected transactions in the ledger and appear in all Reports views

Savings (Emergency Fund & Sinking Funds)

  • Emergency Fund — target amount, current savings, monthly contribution, auto-contribution toggle; progress bar + % badge
  • Sinking Funds — named savings goals with three allocation methods: Fixed Monthly Amount, Annual Cost ÷ 12, or Target Date Planning (app calculates required monthly amount)
  • Auto-contribute — auto-contributions appear as dedicated outflows in the Ledger, Reports, and Account projections
  • Integrated with Reports — contributions appear in Income vs. Expenses, Money Flow chart, Variance Dashboard, and account projections

Account Reconciliation

  • Reconcile page — per-account statement balance entry with a live colour-coded difference vs. tracked balance; explicit statement start/end dates (defaulting to the day after the last reconciliation → today, validated so the end can't precede the start) drive an "Expected transactions" listing that helps identify discrepancies; history rows show the statement period
  • Two modes — Adjust Balance (reconciliation updates startingBalance going forward) or Visible Only (recorded and shown on Ledger but does not mutate the tracked balance); changeable any time via the Settings modal (⚙ gear icon or command palette)
  • Ledger integration — every reconciliation appears as a marker row on the unified Ledger with previous → statement balance and difference; an inline ℹ icon shows whether the current mode is active (blue) or informational (muted)
  • History log — each reconciliation records previous balance, statement balance, difference, and an optional note; per-entry delete does not revert the balance
  • Quick-reconcile modal — "🔄 Reconcile this account" button on the Ledger page (when a single account is selected)
  • Export/Import — app.reconciliations and app.settings round-trip through JSON backup

Ledger

  • Unified transaction list — income, one-time entries, debts, bills, expenses, recurring templates, savings contributions, and reconciliation markers in one scrollable view
  • Account + date range filters — filter by account and by range (All, Past & Today, Next 30/60/90 Days, Through Next Month)
  • Amount overrides — modal-based Override / Edit override / Reset per transaction; overrides are keyed by type+id+account+date so they survive ledger re-sorts; changing an override immediately recalculates running balances, Reports, and account projections
  • Cleared tracking — a Cleared checkbox per transaction records whether it has actually posted to the account, plus the timestamp it was marked cleared (shown as the checkbox's tooltip); keyed the same way as amount overrides, so it's independent of ledger re-sorts. Purely informational — it does not affect running balances — useful for spotting scheduled transactions (bills, recurring items) that haven't posted on the day they were expected to
  • Running balance — continuous balance column; snaps to the statement balance at each reconciliation marker when "Adjust Balance" mode is active
  • CSV export — column-picker modal (date, account, name, amount, category, running balance, type, cleared, cleared at); exports respect the current filter and sort; selected columns persist between sessions

Calendar & Reports

  • Month-by-month calendar — income paydays, recurring occurrences, expenses, debt payments, and bonuses pinned to their dates; compact dot-count cells open a full event modal on click/Enter
  • Income vs. Expenses — chart with income, recurring costs, and debt minimums for the current month
  • Money Flow — cumulative income/outflow/net tracked day-by-day through the month; per-account balance table
  • Variance Dashboard (What Changed) — current vs. previous period deltas for income, expenses, recurring costs, debt minimums, and net available; a Range selector (Single Month/Quarter/Half Year/Year) aggregates across multiple months instead of just one, compared against the equivalent-length prior period
  • Net Worth — historical trend chart (3/6/12 month), Net Worth vs. Liabilities, Asset Growth vs. Debt Reduction, snapshot history audit table, manual snapshot capture; milestone celebrations at +$5K increments
  • Spending Analysis — doughnut pie of all outflows for the selected period; 6-month stacked bar trend; ranked category list with change % badges (vs. prior period or vs. same period last year); drill-down modal per category; the same Range selector as the Variance Dashboard aggregates multiple months (e.g. a quarter) into one view
  • Cash Flow Forecast — project balances 1/2/3/6/12 months ahead for total cash position or a single account; notable-month driver flags; negative-balance and intra-month dip warnings
  • Summary Report — Monthly/Yearly toggle with cash flow, per-account balance changes, and net worth for the selected period
  • Calendar Feed — toolbar 📅 button exports bills, debts, recurring items, expenses, and income paydays (Payday - Name) as all-day iCal events over a ±12-month window; download a .ics file (any backend) or subscribe via a live webcal:// link (PostgreSQL backend). Archived debts follow Settings → Show archived debts and are titled Debt (Archived) - Name when shown

Calculation Engine

  • Daily compounding interest — monthlyInterest = balance × ((1 + APR/365)^daysInMonth − 1)
  • Four strategies — Avalanche (highest APR first), Snowball (lowest balance first), Priority-Low, Priority-High
  • Per-month stimulus — add a one-time extra payment for any month; plan recalculates instantly
  • Negative-amortisation warning — badge flags any debt where the minimum payment is below the monthly interest
  • Strategy comparison panel — runs all four strategies and shows interest/time saved vs. your current choice
  • What-If simulator — drag a slider to add extra monthly payment and instantly see months saved / interest saved
  • Break-Even Analysis — per-debt module (src/breakEven.js) runs two single-debt simulations (plan vs. minimum-only) to compute months saved, interest saved, and balance-over-time series for mini charts; supports both fixed-minimum and percent-of-balance modes
  • Target Payoff Date — enter a desired payoff date; binary-search back-calculator (up to 60 iterations) finds the required monthly payment

Charts (Chart.js)

  • Payoff Timeline — one line per debt declining to zero
  • Cumulative Progress — Total Paid, Principal Paid, Interest Paid running totals
  • Principal vs. Interest doughnut
  • Debt Balance Distribution pie
  • Monthly Debt-to-Income pie (requires income sources)

Data Management

  • Persistent storage — all data auto-saved to localStorage; key debtTrackerData, format "4.0.0". Optional: switch to a self-hosted PostgreSQL backend for multi-device sync
  • JSON export — one-click full backup including accounts, debts, income, bills, expenses, recurring templates, snapshots, overrides, reconciliations, and settings
  • JSON import — Replace (full restore) or Merge (append debts; restore income, bills, expenses, overrides); legacy v1.0 files accepted; 2 MB max; full re-sanitization after import; a collapsible warning list reports any coerced fields or rejected records, and a malformed file shows the specific parse error inline
  • CSV export — debt payment schedule + per-debt summary; Ledger CSV with custom column picker
  • Clear All Data — wipe everything and start fresh

Installable & Offline (PWA)

  • Add to Home Screen / Install — manifest.json plus a generated icon set (icons/) make the app installable as a standalone app on desktop and mobile
  • Offline app shell — a service worker (sw.js) precaches the app shell on first visit, so the app loads with zero network connectivity afterward (your saved data already lives in localStorage, so nothing about it depends on the network either way)
  • Current releases — while online, stable app-shell URLs revalidate before use so Chrome receives newly deployed HTML, JavaScript, and styles instead of retaining an older cached release
  • Update prompt — when a new version is deployed, a dismissible banner offers to reload rather than silently swapping assets mid-session

How to Use

Click ❓ Help in the toolbar to open the full usage guide (guide.html) in a new tab.

1 — Add your debts

Navigate to Liabilities. The page shows the add form and the debt list side by side.

Field Notes
Debt Name Any label (e.g. "Visa", "Car Loan")
Debt Type Credit Card (revolving) or Fixed Amount (recurring)
Balance / Amount Current balance or fixed monthly cost
APR Annual interest rate, e.g. 18.9
Minimum Payment The minimum you must pay each month
Due Date Day of month the payment is due (used in Calendar view)
Priority 1–100, used by Priority strategies
Opened Date Optional — enables the Interest Paid to Date estimate
Category Optional label for filtering

2 — Set up your accounts (optional)

Navigate to Accounts. Define the bank accounts, wallets, or credit cards your money flows through. Each account card shows a projected end-of-month balance factoring in all linked income, debts, and expenses.

3 — Set your strategy and view results

Navigate to Plan.

  1. Enter your Total Monthly Payment.
  2. Choose a Payment Strategy.
  3. Optionally use Back-calculate from target payoff date.
  4. Click Calculate Payment Plan.

Results appear in three tabs:

Tab Contents
📊 Overview Strategy comparison panel; What-If extra-payment simulator
📋 Debt Summary Sortable per-debt table with payoff dates and progress bars; amortization modal
📅 Schedule Tabular (monthly schedule with editable stimulus), Calendar, Chart

Reloading the app later automatically shows your last-calculated plan's results again — no need to re-enter your payment and re-click Calculate. Every submission is also logged to the collapsible 📜 Plan History panel (date, payment, strategy, total interest, payoff date), capped at the 20 most recent runs, so you can compare past plans at a glance.

4 — Track your income

Navigate to Income. Add one row per income source. Use the one-time entry section for bonuses, tax refunds, and irregular deposits.

5 — Track your budget

Navigate to Liabilities (Budget sub-tab). Add bills (fixed monthly costs) and expense budgets (variable spending targets with category and date). The Cash Flow Summary panel shows net remaining after all outflows.

6 — Export / Import

The Backup & Restore button (⇅ icon) is in the top-right toolbar on every page, opening a two-tab modal.

  • Export (JSON) — complete backup of all data as a single .json file
  • Import (JSON) — choose Replace (full restore) or Merge (append debts)
  • Export CSV — payment schedule or Ledger with custom columns
  • Export Charts as PNG — downloads every currently-visible chart as a PNG image
  • Print / Save as PDF — 🖨️ Print button on every page

Payment Strategies Explained

Strategy Order Best for
Avalanche Highest APR first Minimising total interest paid
Snowball Lowest balance first Psychological momentum
Priority – Low first Lowest priority number first Custom ordering (deprioritise debts manually)
Priority – High first Highest priority number first Tackling the most important debt first

The Strategy Comparison panel on the Plan page always shows all four strategies simultaneously.


📚 Technical Details

File Structure

index.html                  — Main page shell + responsive nav + CSP meta tag
guide.html                  — In-app usage guide (opened by Help button)
guide.css                   — Styles for guide.html (externalized for CSP compliance)
styles.css                  — Responsive styles + dark mode + utilities + print stylesheet
styles-csp-classes.css      — CSP-compliant utility classes + dynamic CSS variable rules
manifest.json               — Web app manifest (installability metadata + icon references)
sw.js                       — Service worker: app-shell precache + Chart.js CDN runtime cache
src/
  ├─ app.js                — Main app controller & state (DebtTrackerApp)
  ├─ ui.js                 — Event listeners, page navigation, mobile menu
  ├─ commandPalette.js     — Ctrl+K command palette
  ├─ keyboardShortcuts.js  — Keyboard Shortcuts help panel (KEYBOARD_SHORTCUTS single source of truth)
  ├─ settings.js           — App settings (reconciliation mode, storage backend, etc.)
  ├─ setupWizard.js        — First-run setup wizard + storage backend switcher
  ├─ loginGate.js          — Full-page login gate overlay (PostgreSQL backend only)
  ├─ storageAdapters.js    — Storage backend adapters (LocalStorage / Session / Postgres)
  ├─ serviceWorker.js      — Service worker registration
  ├─ i18n.js               — Internationalization (t(), locale switching, applyStaticTranslations)
  ├─ locales/              — i18n locale dictionaries (en.js, es.js, pl.js)
  ├─ strategy.js           — Payment-plan orchestrator & income widget
  ├─ strategyPlanCalculation.js — Payment-plan calculation entry points
  ├─ strategyCalendar.js   — Payment calendar view
  ├─ strategyComparison.js — Interest comparison & what-if simulator
  ├─ strategySummaryTable.js — Debt summary table & amortization modal
  ├─ strategyScheduleTable.js — Payment schedule table
  ├─ debts.js              — Debt management (CRUD & inline editing)
  ├─ debtBreakEven.js      — Break-even badge, mini chart & accelerate-debt modal
  ├─ accounts.js           — Account management & balance projections
  ├─ bonusAdvisor.js       — Bonus/one-time income advisor
  ├─ income.js             — Income sources & one-time entries
  ├─ bills.js              — Bills data model (no standalone add UI — use Recurring)
  ├─ recurring.js          — Recurring transaction templates
  ├─ savings.js            — Emergency fund & sinking fund tracking
  ├─ ledger.js             — Transaction ledger page rendering & CSV export
  ├─ ledgerTransactions.js — Ledger transaction aggregation (pure computation)
  ├─ ledgerOverrides.js    — Per-transaction manual amount overrides
  ├─ ledgerCleared.js      — Per-transaction cleared/posted tracking with timestamp
  ├─ reconciliation.js     — Account statement reconciliation
  ├─ retirement.js         — Retirement page rendering (account cards, snapshot log, charts, projection, Coast FIRE date)
  ├─ health.js             — Financial health dashboard (DTI, savings rate, runway)
  ├─ spending.js           — Spending analysis (category breakdowns, trends)
  ├─ reports.js            — Reports page orchestrator (month nav)
  ├─ reportsNetWorth.js    — Net worth snapshots & widget
  ├─ reportsCalendar.js    — Reports calendar grid & day-detail modal
  ├─ reportsCashFlow.js    — Income/expense & money flow reports
  ├─ reportsMoneyFlowSankey.js — Money Flow Sankey chart
  ├─ reportsVariance.js    — Budget variance report
  ├─ reportsSummary.js     — Reports summary metrics
  ├─ forecast.js           — Cash Flow Forecast (Reports tab)
  ├─ charts.js             — Chart rendering & lifecycle
  ├─ storage.js            — Persistence (save/load/quota/backend switching)
  ├─ sanitizers.js         — Sanitizers for persisted/imported record shapes
  ├─ dataExport.js         — JSON/CSV export & import
  ├─ dataTransferModal.js  — Postgres-to-local data transfer modal
  ├─ postgresSync.js       — Per-resource Postgres mutation helpers (pgPost/pgPatch/pgDelete)
  ├─ postgresImport.js     — loadFromPostgres() fan-out to all 15 resource endpoints
  ├─ pgMigrationModal.js   — One-time local→Postgres migration modal
  ├─ breakEven.js          — Per-debt break-even calculation engine (plan vs. min-only)
  ├─ debtCalculator.js     — Pure calculation engine (no side effects, no DOM access)
  ├─ retirementCalculator.js — Pure retirement projection engine (future-value projection, growth/contribution split, Coast FIRE)
  ├─ guideTheme.js         — Applies saved dark-mode theme to guide.html
  ├─ guideNav.js           — In-app guide navigation helpers
  └─ utils.js              — Formatting, date utilities, sanitization, chart tables
server/                     — Optional self-hosted Node.js + PostgreSQL backend
  ├─ src/index.js          — Express app (auth, CRUD routes, CSRF, rate-limiting)
  ├─ migrations/           — node-pg-migrate SQL migration files
  ├─ scripts/create-user.js — Bootstrap admin user (argon2id hashed)
  ├─ docker-entrypoint.sh  — Reads Docker secret → sets DATABASE_URL before Node starts
  ├─ Dockerfile            — node:24-alpine image (build context = repo root for sanitizer reuse)
  └─ README.md             — Server setup, dev, and deployment guide
tests/ (778 tests across 81 files)
  ├─ conftest.py              — Shared fixtures & utilities
  ├─ README.md                — Comprehensive test documentation
  ├─ security/ (65 tests)     — XSS, CSP, input validation, static scan
  │   ├─ test_xss.py, test_csp.py
  │   └─ test_input_validation.py, test_static_scan.py
  ├─ features/ (389 tests)    — Per-feature CRUD, calculations, business logic
  │   ├─ test_accounts.py, test_debts.py, test_income.py, test_bills.py
  │   ├─ test_expenses.py, test_recurring.py, test_recurring_occurrences.py
  │   ├─ test_ledger.py, test_reports.py, test_savings.py, test_networth.py
  │   ├─ test_health.py, test_forecast.py, test_reconciliation.py
  │   ├─ test_spending_analysis.py, test_storage_import.py, test_storage_quota.py
  │   ├─ test_debt_calculator.py, test_strategy.py, test_settings.py
  │   ├─ test_main_nav_groups.py, test_reports_nav_groups.py, test_versioning.py
  │   ├─ test_break_even.py, test_interest_income.py, test_i18n.py, test_i18n_coverage.py
  │   ├─ test_storage_backend.py, test_pwa.py, test_pwa_icons.py, test_analytics.py
  │   ├─ test_cash_flow_trend.py, test_money_flow_sankey.py, test_validation_modals.py
  │   └─ test_issue_92_export.py, test_issue_93_expense_save.py
  ├─ ui/ (249 tests)          — UI/UX, responsiveness, accessibility
  │   ├─ test_mobile.py, test_modals.py, test_dark_mode.py, test_high_contrast_theme.py
  │   ├─ test_css_load.py, test_accessibility.py, test_main_nav.py
  │   ├─ test_charts.py, test_chart_accessibility.py, test_guide_theme.py
  │   ├─ test_guide_nav.py, test_reduced_motion.py, test_command_palette.py
  │   ├─ test_setup_wizard.py, test_overview_print.py, test_remaining_pages_print.py
  │   ├─ test_table_mobile_scroll.py, test_data_transfer_modal.py, test_delete_confirm_modal.py
  │   ├─ test_settings_theme_location.py, test_pwa_update_banner.py
  │   ├─ test_debt_actions.py, test_recurring_actions.py, test_reports_actions.py
  │   └─ test_reports_nav.py, test_reconciliation_actions.py, test_spending_ui.py, test_strategy_calendar.py, test_whatif_simulator.py
  ├─ a11y/ (10 tests)         — Site-wide WCAG 2.1 AA accessibility audit
  │   └─ test_a11y_audit.py, run_a11y_audit.py
  ├─ integration/ (18 tests)  — End-to-end workflows, import/export, data persistence
  │   ├─ test_smoke.py, test_workflows.py, test_interest_income_workflow.py
  │   └─ test_pwa_offline.py
  └─ postgres/ (47 tests — requires Docker stack)
      ├─ test_postgres_bootstrap.py     — Auth, login gate, session handling
      ├─ test_postgres_import.py        — loadFromPostgres fan-out + import round-trip
      ├─ test_postgres_mutations.py     — Per-resource CRUD via pgPost/pgPatch/pgDelete
      ├─ test_postgres_migration.py     — local→Postgres one-time migration modal flow
      ├─ test_postgres_notifications.py — Mailpit-backed end-to-end coverage for the test-email flow
      └─ test_postgres_setup_wizard.py  — First-run setup wizard against the Postgres backend
tools/
  ├─ debug/                   — Ad-hoc manual debugging scripts (not part of pytest suite)
  └─ generate-icons.js        — One-time PWA icon generator (Node zlib only, not run in CI)
icons/                        — Generated PWA icon set (tools/generate-icons.js output)

Known gap: The standalone Bills UI (#billForm/#billList) was removed in favor of Recurring Templates, but bills.js still defines the full bills data model and calculation logic — app.bills is read by accounts.js, health.js, ledger.js, and strategy.js, and round-trips through import/export. There is currently no reachable UI to add or edit a bill.

Documentation Files

Key Technologies

  • Frontend: Vanilla ES6+ JavaScript — no frameworks, no build step
  • Storage: Browser localStorage (same-origin isolated); optional self-hosted PostgreSQL backend
  • Charts: Chart.js 4.4.3 via CDN
  • Testing: pytest + Playwright (browser automation)

Formulas & Algorithms

Interest Calculation (Daily Compounding)

monthlyInterest = balance × ((1 + APR / 100 / 365)^daysInMonth − 1)

Interest Paid to Date

totalAccrued = originalBalance × ((1 + APR/100/365)^daysSinceOpened − 1)
interestPaid = max(0, totalAccrued − principalPaidDown)

Target Payoff Date Back-Calculator (Binary Search)

lo  = sum of all minimum payments
hi  = 2 × totalBalance + 10,000
for 60 iterations:
    mid = (lo + hi) / 2
    if calculatePaymentPlan(mid) pays off by target date → hi = mid
    else → lo = mid

Security Implementation

Input Validation & Sanitization

  • normalizeText() — strips dangerous characters from text fields
  • sanitizeFiniteNumber() — validates numbers with optional min/max bounds
  • sanitizeInteger() — integer validation
  • sanitizeDateISO() — strict YYYY-MM-DD format validation
  • escapeHtml() — HTML entity encoding for all output via innerHTML

Import Safety

  • Maximum file size: 2 MB
  • JSON validation with try-catch — a malformed file surfaces the native parse error (position/line/column when the browser provides it) inline in the Import tab's error banner, never a popup alert
  • Complete re-sanitization on every import (all sanitize* functions run again)
  • Per-field coercion/rejection warnings — a collapsible "Import succeeded — N issues found" list names every field that was coerced to a default and every record dropped for missing/invalid required fields, across all importable collections
  • Duplicate detection and filtering
  • Type checking on all fields

Content Security Policy (CSP)

default-src 'self';
script-src 'self' https://cdn.jsdelivr.net;
style-src 'self';
img-src 'self' data:;
font-src 'self';
connect-src 'self' https://cdn.jsdelivr.net;
object-src 'none';
base-uri 'self';
form-action 'self'

frame-ancestors 'none' is enforced via X-Frame-Options: DENY HTTP header (browsers ignore frame-ancestors in <meta> CSP tags per spec). Server deployments in DEPLOYMENT.md add it via the HTTP CSP header.


🧪 Testing Suite (Updated September 4, 2026)

Test Statistics

  • Total Tests: 731 comprehensive tests (plus 47 Postgres/CI-only), all passing
  • Test Files: 74 organized across 6 categories (81 including postgres/)
  • Framework: pytest with Playwright browser automation
  • Coverage: All major features + security + UI + accessibility + integration paths

Test Categories

🔐 Security Tests (65 tests)

  • XSS Prevention — Input sanitization across accounts, income, debts, recurring, savings, reconciliation, spending, health, ledger
  • CSP Compliance — Strict Content Security Policy enforcement; meta tag / nginx header sync check
  • Input Validation — Bounds checking, unicode, special characters, negative-amount guards on all forms
  • Static Analysis — Code patterns, hardcoded secrets, dependencies

🎯 Feature Tests (389 tests)

  • Accounts — CRUD, projections, graceful orphaning of linked items on deletion; interest-rate (% APY) badge display — threshold/formatting boundaries, multi-account scoping, edit-to-clear, reload persistence, import clamping
  • Debts — Liability management, interest, amortization, fixed-amount validation
  • Interest Income — monthly compounding deposit engine, last-day posting, override-aware compounding, negative/zero/sub-cent skips, Reports/Forecast integration
  • Debt Calculator — Strategies (incl. multi-debt priority ordering), daily compounding, back-calculator, stimulus edge cases
  • Strategy / Plan — Avalanche/Snowball/Priority switching, comparison panel, stimulus validation, plan history logging/cap, last-plan restore on load
  • Income — Sources, frequencies, totals, negative-amount rejection (add + inline edit paths)
  • Expenses — Add/edit/delete, amount/date validation
  • Bills — Data model, sanitization, calculation integration
  • Recurring — All frequencies, pause/resume, skip-month, mark-as-paid, account linkage, validation
  • Ledger — Filtering, amount-override modal, cleared-checkbox tracking, key collision checks, CSV export column picker
  • Reports — Income vs expenses, money flow, net worth analytics, tab grouping, date-boundary handling
  • Savings — Emergency funds, sinking funds, persistence
  • Net Worth — Snapshots, milestones, historical calculations
  • Financial Health — All six cards, empty states, nav links
  • Cash Flow Forecast — Horizon/account selection, notable months, negative-balance warnings, intra-month dip detection
  • Account Reconciliation — Statement balance adjustments, expected-transaction matching, sanitization, import/export
  • Spending Analysis — Category breakdowns, month-over-month trends
  • Settings — Reconciliation mode persistence and import/export round-trip
  • Storage Import — Sanitizer primitives, adversarial inputs for all record types, legacy v1.0 format
  • Storage Quota — Soft warning at ~80%, dismissibility, re-arming, hard-failure on write error
  • Main Nav Groups — Grouped navigation structure (Overview/Manage/Analyze)
  • Break-Even Analysis — badge no-plan and plan-active states, min-type toggle, accelerate modal (open/preview/apply), plan table columns, fixed-amount exclusion, edge cases (0% APR, balance=minimum, invalid percent, $0/$negative extra)
  • Analytics — optional self-hosted Google Analytics stays off with no window.__ENV__.GA_MEASUREMENT_ID; injects gtag.js/dataLayer when it's present; index.html/guide.html wiring

🎨 UI/UX Tests (249 tests)

  • Mobile Responsiveness — Hamburger menu, viewport handling, touch sizing, table horizontal scroll
  • Modals — Visibility toggling, close buttons, amortization, calendar day-detail, ledger export
  • Dark Mode — Theme switching, contrast, persistence, corrupted-localStorage fallback
  • High Contrast Theme — 3-way selector wiring, dark-mode+high-contrast-mode class pairing, persistence, corrupted-value fallback, focus-ring, .nav-group-label contrast regression guard
  • CSS Loading — External stylesheet, utility classes, responsive breakpoints
  • Accessibility — Keyboard navigation, ARIA labels, semantic HTML, Results tab-bar semantics
  • Guide Theme — guide.html dark/light mode sync, nav back-link
  • Charts — Chart.js instance destroy-before-recreate on repeated re-render
  • Chart Accessibility — .sr-only data-table fallback present for health, spending, forecast, net-worth, strategy, and budget cash-flow charts
  • Reduced Motion — CSS transition-duration collapse and Chart.defaults.animation disabled under prefers-reduced-motion
  • Command Palette — Ctrl+K / toolbar open, filtering, empty-state, arrow-key navigation, Enter-to-navigate, Escape/backdrop close
  • Keyboard Shortcuts Panel — palette command + account-menu entry points, rows match KEYBOARD_SHORTCUTS, focus trap, Escape/backdrop close with focus restore, CSP-safe rendering
  • Setup Wizard — First-run modal, setting persistence, skip flow
  • Print Buttons — Present on Overview pages (Health/Accounts/Income) and all remaining pages; @media print stylesheet hides forms
  • Table Mobile Scroll — Ledger, reconciliation expected, and report tables scroll within .table-wrapper on narrow viewports
  • Main Nav — Grouped active-state highlighting and keyboard reachability
  • Reports Nav / Actions — Tab-bar grouping, sticky positioning, dark mode, tab-switching visibility
  • Debt / Recurring / Reconciliation Actions — Inline edit, mark-paid, reconcile-modal flows
  • Spending UI — Pie/bar charts, ranked list, drill-down modal

♿ Accessibility Audit (10 tests)

Site-wide sweep across all 10 pages × 2 themes + guide.html: dangling ARIA refs, duplicate IDs, orphaned form inputs, unnamed interactive elements, missing alt text, computed WCAG 1.4.3 colour contrast, modal Escape-to-close, mobile nav aria-expanded.

🔄 Integration Tests (18 tests)

  • End-to-End Workflows — Complete user journeys (account → debt → net worth → reconciliation)
  • Data Persistence — Cross-navigation data integrity
  • Import/Export — JSON roundtrip, CSV schedule export (incl. comma/quote escaping), full clear-all-data → reimport → render-every-page consistency check
  • Ledger CSV Export — Column-picker modal (incl. cleared/cleared-at columns), filtered export, column persistence

Quick Test Commands

pytest tests/ -v                  # All 778 tests (requires Docker for postgres/)
pytest tests/security/ -v         # 65 security tests
pytest tests/features/ -v         # 389 feature tests
pytest tests/ui/ -v               # 249 UI/UX tests
pytest tests/a11y/ -v             # 10 accessibility audit tests
pytest tests/integration/ -v      # 18 integration tests
pytest -m "security" -v           # All security tests by marker
pytest -m "not slow" -v           # Skip slow tests

🧬 Mutation Testing (Jest + Stryker)

A separate, dev-only Node toolchain mutation-tests the pure calculation/formatting/sanitization functions in src/debtCalculator.js, src/utils.js, and src/sanitizers.js — not the Python suite above. It runs as the mutation-testing job in CI (.github/workflows/ci.yml).

npm install
npm run test:unit        # Jest unit tests
npm run test:mutation     # Stryker mutation run (HTML report at reports/mutation/mutation.html)

Security Scan Results (June 19, 2026)

Severity Count Status
HIGH 0 ✅
MEDIUM 0 ✅
LOW 12 ✅ All properly handled

📱 Browser Support & Requirements

Browser Version Support
Chrome 60+ ✅ Full
Firefox 55+ ✅ Full
Safari 12+ ✅ Full
Edge 79+ ✅ Full
IE 11 — ❌ Not supported

Required: ES6+ JavaScript, localStorage enabled, CSS Grid & Flexbox, CSS custom properties.


🚀 Deployment

# Development
python -m http.server 32900

See DEPLOYMENT.md for Nginx, Apache, and Docker configurations including security headers, HTTPS, and caching.


🐛 Troubleshooting

My data disappeared.

Browser storage may have been cleared. Use Backup & Restore → Export regularly as a portable JSON backup you can re-import any time.

Import says "duplicate skipped" but I wanted to update.

Delete or rename the existing item first, then re-import. Or use inline editing to update manually.

The payoff date is very far away.

Increase your monthly payment, switch to Avalanche strategy, or use the What-If slider to see required payment increase.

Payment is less than minimum required.

The app will show an error. Your total monthly budget must cover every debt's minimum payment.

A debt shows a ⚠️ neg-amort badge.

Your minimum payment is too low to cover monthly interest. Increase the payment or reduce the APR (e.g. balance transfer).

Mobile menu isn't working.

Check that JavaScript is enabled and no CSP violations appear in the browser console.

Data isn't persisting between refreshes.

Verify localStorage is enabled. Safari may require explicit permission in Storage settings.

The storage quota warning appeared.

Export a JSON backup immediately. Consider clearing old net-worth snapshots or unused data to free space.


📞 Support & Contributions

Security Issues

If you discover a security vulnerability:

  1. Do not create a public GitHub issue
  2. Contact the repository owner privately
  3. Include steps to reproduce + impact assessment
  4. See SECURITY.md for details

Bug Reports

Open an issue with steps to reproduce, browser version, and OS. Run the test suite and include output.

Contributions

  • All changes should pass the security and feature test suites
  • Add tests for new features (security, feature, and UI coverage)
  • Follow the existing modular pattern: feature logic in a module function featureFn(app, ...), thin wrapper on DebtTrackerApp
  • All user-supplied strings rendered via innerHTML must use escapeHtml()
  • New persisted fields must have a sanitize* entry in storage.js
  • See SECURITY.md for security guidelines and ROADMAP.md for planned work

Start your journey to being debt-free today! 💰


MyFinances v4.45.0 — Updated September 4, 2026

About

MyFinances is a client-side personal finance tracking application with strong security practices. This document outlines the security measures implemented and best practices for deployment and usage.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0