Private
Public Access
1
0
Files
Purrse/README.md
T
Catherine Renelle ce050a73b5 Add MIT license
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 19:13:10 -05:00

181 lines
7.9 KiB
Markdown

# Purrse
A self-hosted personal finance manager built with ASP.NET Core and Vue 3.
> **Work in Progress** — Purrse is under active development and subject to change. Features may be added, removed, or reworked without notice.
> **Source Code Note** — GitHub is not the primary repository for this project. The GitHub mirror is updated periodically and may not always reflect the latest state of development.
## About
Purrse is a self-hosted personal finance application for tracking accounts, transactions, budgets, loans, investments, and more. It supports automatic bank syncing via SimpleFIN and Plaid, AI-powered transaction categorization and chat through a local Ollama LLM, and multi-format file imports.
### AI-Assisted Development
Purrse is developed with the assistance of [Claude Code](https://docs.anthropic.com/en/docs/claude-code), Anthropic's CLI tool for AI-assisted software development. Claude Code contributes to feature implementation, code review, refactoring, and security hardening throughout the project.
## Tech Stack
| Layer | Technology |
|-------|-----------|
| Backend | ASP.NET Core 9 (.NET 9) |
| Frontend | Vue 3, TypeScript, Vuetify 3 |
| Database | PostgreSQL 17 |
| ORM | Entity Framework Core 9 |
| Real-time | SignalR |
| Charts | ApexCharts |
| AI | Ollama (local LLM) |
| Bank Sync | SimpleFIN, Plaid |
| Containerization | Docker Compose |
## Features
### Financial Management
- **Accounts** — Checking, savings, credit card, loan, mortgage, brokerage, retirement, and more
- **Transactions** — Full CRUD with categorization, payee tracking, transfers, and status management (pending, cleared, reconciled)
- **Budgets** — Monthly budgets with per-category targets and actual vs. planned tracking
- **Scheduled Transactions** — Recurring transactions with automatic posting via background service
- **Loans** — Amortization schedules, payoff scenarios, and interest tracking
- **Investments** — Holdings management with security prices, cost basis, gain/loss, and performance tracking
- **Reconciliation** — Bank statement reconciliation workflow
- **Reports** — Spending by category, income vs. expense, net worth over time, cash flow analysis
- **Dashboard** — Net worth, account summaries, recent transactions, spending breakdown, upcoming bills
### Bank Sync
- **SimpleFIN** — Open banking standard for automatic transaction syncing
- **Plaid** — Account aggregation with sandbox, development, and production environments
- **Background Sync** — Configurable sync intervals with automatic background processing
- **Duplicate Detection** — FitId matching and fuzzy fingerprint-based deduplication
- **Sync History** — Detailed logs with import/skip counts and error tracking
### AI Features (Ollama)
- **Transaction Categorization** — Automatic classification with configurable confidence thresholds and customizable prompts
- **Chat Assistant** — Conversational finance assistant with tool-calling support for querying transactions, spending reports, balances, budgets, and more
- **Local Processing** — All AI processing runs locally via Ollama; no data is sent to external services
### Data Import
- **OFX** (Open Financial Exchange)
- **CSV** (Comma-Separated Values)
- **QIF** (Quicken Interchange Format)
- Import preview with duplicate detection and batch confirmation
### Plugin System
- Extensible architecture for file parsers and bank sync providers
- Automatic plugin discovery and loading at startup
## Security & Encryption
Purrse handles sensitive financial data and takes security seriously:
### Authentication & Authorization
- **JWT Bearer Authentication** with configurable expiration and zero clock skew
- **BCrypt Password Hashing** with a work factor of 12
- **Refresh Token Security** — tokens are SHA-256 hashed before database storage; raw tokens are never persisted
- **Password Strength Validation** — minimum 8-character requirement enforced server-side
- **User Isolation** — all API endpoints enforce `userId` scoping via JWT claims; users can only access their own data
### Encryption
- **AES-256-GCM Authenticated Encryption** for bank sync credentials (access tokens, API keys)
- **HKDF Key Derivation** (SHA-256) to derive encryption keys from the configured master key
- **Versioned Encryption Format** — ciphertext includes a version byte prefix for forward-compatible algorithm upgrades
### API Security
- **Rate Limiting** — sliding window rate limiter on all endpoints (10 req/min for auth, 120 req/min for general API)
- **SSRF Protection** — Ollama URL validation blocks private IPs, IPv6-mapped addresses, link-local ranges, and cloud metadata endpoints
- **IDOR Prevention** — all resource access verified against authenticated user; no cross-user data access
- **File Upload Limits** — 10 MB maximum with filename sanitization
- **Pagination Caps** — server-enforced maximum page size (200) to prevent data exfiltration
- **Input Validation** — parameterized queries throughout; no raw SQL interpolation
### Transport & Headers
- **Security Headers** — `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Strict-Transport-Security`, `Referrer-Policy`, `X-Permitted-Cross-Domain-Policies`, `Cache-Control: no-store`
- **CORS** — configured origin allowlist with credential support
- **PostgreSQL SSL** — connections use `Ssl Mode=Prefer` with certificate trust
### Production Safeguards
- **Startup Validation** — application refuses to start in Production if JWT key or encryption key are still set to defaults
- **Account Number Masking** — only the last 4 digits are returned by the API
## Quick Start
### Prerequisites
- [Docker](https://www.docker.com/) and Docker Compose
### Run with Docker Compose
1. Clone the repository:
```bash
git clone https://github.com/yourusername/Purrse.git
cd Purrse
```
2. Copy the environment example and configure:
```bash
cp .env.example .env
```
Edit `.env` and set your secrets:
```env
DB_PASSWORD=your_secure_database_password
JWT_KEY=YourSuperSecretKeyHere_AtLeast32Characters!
BANKSYNC_ENCRYPTION_KEY=your_32_char_aes256_key_here!!!!
```
Generate a secure encryption key:
```bash
openssl rand -base64 32
```
3. Start the application:
```bash
docker compose up -d
```
4. Access Purrse:
- **Frontend**: http://localhost:9080
- **API**: http://localhost:5000
### Default Ports
| Service | Port |
|---------|------|
| Frontend | 9080 |
| API | 5000 |
| PostgreSQL | 5433 |
### Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `DB_PASSWORD` | PostgreSQL password | `purrse_dev` |
| `JWT_KEY` | JWT signing key (min 32 chars) | Dev default (blocked in production) |
| `BANKSYNC_ENCRYPTION_KEY` | AES-256 encryption key for bank credentials | Dev default (blocked in production) |
| `ASPNETCORE_ENVIRONMENT` | Runtime environment | `Development` |
## Project Structure
```
Purrse/
├── src/
│ ├── Purrse.Api/ # ASP.NET Core API
│ │ ├── Controllers/ # REST endpoints
│ │ ├── Services/ # Business logic
│ │ ├── Hubs/ # SignalR real-time
│ │ └── Middleware/ # Request logging, error handling
│ ├── Purrse.Core/ # Domain models, DTOs, interfaces
│ ├── Purrse.Data/ # EF Core DbContext & migrations
│ └── Purrse.Plugins.*/ # File parsers & bank sync providers
├── frontend/ # Vue 3 + Vuetify SPA
│ └── src/
│ ├── views/ # Page components
│ ├── components/ # Reusable components
│ ├── services/ # API clients
│ ├── stores/ # Pinia state management
│ └── types/ # TypeScript definitions
└── docker-compose.yml
```
## License
This project is licensed under the [MIT License](LICENSE).