From 70db18e89f32a945b0d618f6b4a8dc56fc743509 Mon Sep 17 00:00:00 2001 From: megaproxy Date: Tue, 21 Apr 2026 15:00:48 +0000 Subject: [PATCH] Add README for MyMidas Full project documentation covering features, security architecture, tech stack, setup instructions, backup/key rotation, and env vars. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..4cef08e --- /dev/null +++ b/README.md @@ -0,0 +1,254 @@ +# MyMidas + +A self-hosted, single-user personal finance tracker built for security and completeness. Combines budgeting, investment tracking, and ML-powered predictions in one application — things that no single open-source tool does together. + +Runs entirely on your own hardware via Docker Compose. Designed for LAN access with VPN for remote, behind an existing reverse proxy (nginx proxy manager, Caddy, etc.). + +--- + +## Features + +### Accounts & Transactions +- Multiple account types: Checking, Savings, Cash ISA, Stocks & Shares ISA, Credit Card, Investment, Pension, Crypto Wallet, Loan, Mortgage, and more +- Full transaction history with categories, tags, merchant tracking, and notes +- Transfer detection between accounts +- Recurring transaction rules (rrule) +- Receipt and document attachments on transactions (JPEG, PNG, WebP, PDF — up to 10 MB each) +- CSV import with **auto-detection** for 10 UK bank formats: Monzo, Starling, Revolut, Barclays, Lloyds, NatWest, HSBC, Santander, Nationwide, and generic fallback +- SHA-256 deduplication prevents re-importing the same transactions + +### Budgets +- Monthly, weekly, quarterly, and yearly budget periods +- Per-category budget tracking with rollover support +- Visual radial gauges showing spend vs. budget +- Configurable alert threshold (default 80%) + +### Investments +- Portfolio tracking with holdings and buy/sell/dividend/split transactions +- Live price feeds: stocks and ETFs via **yfinance**, crypto via **CoinGecko** (refreshed every 15 minutes) +- Hourly FX rates for multi-currency conversion to GBP base +- TWRR and MWRR performance metrics +- Capital gains reporting (short/long-term by tax year) +- OHLCV candlestick charts per asset +- Allocation treemap across the full portfolio + +### Reports +Seven report views: +1. Net Worth over time (area chart with time slider) +2. Income vs. Expense (bar chart) +3. Cash Flow (waterfall) +4. Category Breakdown (pie with drilldown) +5. Budget vs. Actual +6. Investment Performance +7. Spending Trends + +Export to CSV and PDF. + +### ML Predictions +Four prediction engines, all running locally: + +| Engine | Algorithm | Output | +|--------|-----------|--------| +| **Spending Forecast** | Meta Prophet per category; SARIMA fallback | 90-day forecast with 80%/95% confidence bands | +| **Net Worth Projection** | Holt-Winters ExponentialSmoothing | 1/3/5-year fan chart, 3 scenarios (conservative/base/optimistic) | +| **Monte Carlo Portfolio** | Geometric Brownian Motion + Cholesky covariance | 1,000–5,000 simulations, P10–P90 percentile paths | +| **Budget Forecast** | Velocity-based daily projection + normal CDF | Probability of overspend per category this month | + +Plus a 30-day cash flow forecast with negative-balance risk flagging. + +### Themes +Seven selectable UI themes — pick from the top bar: + +| Theme | Style | +|-------|-------| +| **Obsidian** | Dark slate, blue-grey accents | +| **Arctic** | Clean light with ice-blue tones | +| **Midnight** | Deep navy with cyan highlights | +| **Vault** | Forest green, financial gravitas | +| **Terminal** | Phosphor green on black, scanline overlay, monospace | +| **Synthwave** | Neon pink/purple, grid lines, Orbitron headings | +| **Ledger** | Warm paper, serif typography, ruled lines | + +--- + +## Security + +Ten independent security layers: + +1. **Network isolation** — Postgres and Redis are on an internal Docker bridge, never exposed to the host +2. **TLS** — handled upstream by your reverse proxy; internal traffic is HTTP (LAN-only) +3. **Security headers** — CSP, HSTS, X-Frame-Options DENY, X-Content-Type-Options, form-action, Permissions-Policy +4. **CSRF** — double-submit cookie on all mutating endpoints +5. **Authentication** — Argon2id password hashing; RS256 JWT (15-min access + 7-day HttpOnly refresh cookie); TOTP (RFC 6238) with backup codes; brute-force lockout (exponential backoff via Redis) +6. **Rate limiting** — Redis sliding window: 10/min on auth, 10/min on TOTP, 20/min on predictions, 300/min general API +7. **Field-level encryption** — AES-256-GCM on all PII fields (account names, transaction descriptions, merchant, notes, TOTP secret); IV ‖ ciphertext ‖ tag stored in `bytea` +8. **Database encryption** — pgcrypto as a second layer on backup dumps +9. **Row-level security** — PostgreSQL RLS policies enforce user isolation at the DB layer; buggy queries cannot leak another user's data +10. **Audit log** — every auth event and data mutation is written to an append-only `audit_logs` table; the app role has no UPDATE/DELETE on it + +**Single-user hardening:** registration is permanently disabled after the first account is created. Re-enable with `ALLOW_REGISTRATION=true` if needed. + +--- + +## Tech Stack + +| Layer | Technology | +|-------|-----------| +| Backend | Python 3.12, FastAPI, SQLAlchemy 2.0 async | +| Frontend | React 18, TypeScript, Vite, TanStack Query v5 | +| Styling | Tailwind CSS v4, shadcn/ui primitives | +| Charts | Recharts (standard), Plotly (Monte Carlo, candlestick) | +| Database | PostgreSQL 16 with pgcrypto and RLS | +| Cache / Sessions | Redis 7 | +| ML | Prophet, statsmodels, NumPy, SciPy | +| Background jobs | APScheduler (in-process) | +| Containerisation | Docker Compose | + +--- + +## Getting Started + +### Prerequisites +- Docker and Docker Compose +- An existing reverse proxy (nginx proxy manager, Caddy, Traefik, etc.) pointing at port `8090` + +### 1. Clone and configure + +```bash +git clone https://git.rdx4.com/megaproxy/MyMidas.git +cd MyMidas +cp .env.example .env +``` + +Edit `.env` and fill in every value: + +```env +# 32-byte hex key — generate with: +# python3 -c "import secrets; print(secrets.token_hex(32))" +ENCRYPTION_KEY= + +# Strong random passwords +DB_PASSWORD= +REDIS_PASSWORD= +BACKUP_PASSPHRASE= + +BASE_CURRENCY=GBP +ENVIRONMENT=production +ALLOW_REGISTRATION=false # set true only for initial account creation +``` + +### 2. Generate JWT keys + +```bash +mkdir -p secrets +openssl genrsa -out secrets/jwt_private.pem 4096 +openssl rsa -in secrets/jwt_private.pem -pubout -out secrets/jwt_public.pem +``` + +### 3. Start + +```bash +docker compose up -d --build +``` + +All four containers start: `backend`, `frontend`, `postgres`, `redis`. + +### 4. Create your account + +Temporarily set `ALLOW_REGISTRATION=true` in `.env`, restart the backend, register, then set it back to `false`: + +```bash +# In .env: ALLOW_REGISTRATION=true +docker compose up -d backend + +# Register via the web UI, then: +# In .env: ALLOW_REGISTRATION=false +docker compose up -d backend +``` + +### 5. Point your reverse proxy + +Forward your domain to `http://:8090`. The frontend is served from port `4000` internally but the backend proxies frontend assets — point everything at `8090`. + +--- + +## Backups + +Encrypted nightly backup runs automatically at 3 AM: + +```bash +# Manual backup +docker compose exec -e BACKUP_PASSPHRASE="$BACKUP_PASSPHRASE" backend bash scripts/backup.sh + +# List backups +docker compose exec backend bash scripts/restore.sh --list + +# Restore +docker compose exec -e BACKUP_PASSPHRASE="$BACKUP_PASSPHRASE" \ + -e DATABASE_URL="$DATABASE_URL" \ + backend bash scripts/restore.sh 20240101_030000.sql.gz.gpg +``` + +Backups are stored in `./data/backups/` and retained for 30 days. + +## Key Rotation + +To rotate the AES-256-GCM encryption key without data loss: + +```bash +# Generate new key +NEW_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))") + +# Stop the app, rotate, update .env, restart +docker compose stop backend +NEW_ENCRYPTION_KEY="$NEW_KEY" ./scripts/rotate_keys.sh +# Update ENCRYPTION_KEY in .env to $NEW_KEY +docker compose up -d backend +``` + +--- + +## Environment Variables + +| Variable | Description | Default | +|----------|-------------|---------| +| `ENCRYPTION_KEY` | 32-byte hex key for AES-256-GCM field encryption | **required** | +| `DB_PASSWORD` | PostgreSQL password | **required** | +| `REDIS_PASSWORD` | Redis password | **required** | +| `BACKUP_PASSPHRASE` | GPG symmetric passphrase for backup encryption | **required** | +| `BASE_CURRENCY` | ISO 4217 base currency | `GBP` | +| `ENVIRONMENT` | `production` or `development` | `production` | +| `ALLOW_REGISTRATION` | Enable new account creation | `false` | + +--- + +## Project Structure + +``` +MyMidas/ +├── backend/ +│ ├── app/ +│ │ ├── api/v1/ # REST endpoints +│ │ ├── core/ # Security, encryption, middleware, rate limiting +│ │ ├── db/ # Models, migrations, repositories +│ │ ├── ml/ # Prediction engines +│ │ ├── services/ # Business logic +│ │ └── workers/ # Scheduled jobs (price sync, FX, snapshots, backups) +│ └── alembic/ # Database migrations +├── frontend/ +│ └── src/ +│ ├── api/ # Typed API client +│ ├── components/ # Shared UI components +│ ├── pages/ # Route-level page components +│ └── store/ # Zustand state (auth, UI/theme) +├── postgres/init/ # PostgreSQL init SQL (extensions, RLS policies) +├── scripts/ # backup.sh, restore.sh, rotate_keys.sh +├── secrets/ # JWT keys (git-ignored, generate locally) +└── docker-compose.yml +``` + +--- + +## Licence + +Personal use. Not intended for public deployment or multi-user hosting.