From bfc1521835486bc8a35893d927db842949d675b7 Mon Sep 17 00:00:00 2001 From: null Date: Fri, 15 May 2026 22:52:28 -0500 Subject: [PATCH] v0.28.0 --- README.md | 387 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 226 insertions(+), 161 deletions(-) diff --git a/README.md b/README.md index 4dbf9ea..5d60c8d 100644 --- a/README.md +++ b/README.md @@ -1,56 +1,104 @@ # BillTracker

- Tracker logo + BillTracker logo

-BillTracker is a self-hosted app for tracking recurring bills, monthly payments, due dates, categories, and personal bill history. It runs as a Node/Express server with a React frontend and stores data in SQLite. This product was produced with the assistance of AI. +BillTracker is a private, self-hosted bill planning app for households and small personal setups. It tracks recurring bills, payments, monthly cash buckets, due dates, categories, debt payoff, imports, exports, and backups from one local installation. + +It runs as a Node/Express app with a React/Vite frontend and stores data in SQLite. It is designed for people who want their bill data under their own control instead of inside a third-party budgeting service.

Demo Server: https://t1.scheller.ltd/
Username: guest · Password: guest123

+## Highlights + +- Private-by-design self-hosted bill tracking with local SQLite storage +- Month-by-month tracker grouped by `1st-14th` and `15th-31st` +- Period-aware remaining balance that switches between the 1st and 15th buckets +- Bills, categories, payments, notes, skipped months, history ranges, and inactive bill handling +- Debt snowball page with payoff projections, avalanche comparison, APR math, and amortization schedules +- Analytics, calendar, monthly summary, income, starting cash, and printable reports +- XLSX import, import by bill, user export/import, Excel export, import history, and admin backups +- Local username/password login with optional authentik/OIDC +- Admin panel for users, backups, cleanup, auth settings, system status, roadmap, and migrations +- Public About, Privacy, and Release Notes pages + ## Screenshots -![Analytics screenshot](docs/images/login.png) -![Analytics screenshot](docs/images/tracker.png) +![Login screenshot](docs/images/login.png) +![Tracker screenshot](docs/images/tracker.png) ![Analytics screenshot](docs/images/Analytics.png) ![Calendar screenshot](docs/images/Calendar.png) -## What Is BillTracker? +## Who This Is For -BillTracker helps a household or small self-hosted setup keep bill data in one place: +BillTracker is built for self-hosters who want a practical bill dashboard without sending personal finance data to an outside service. -- recurring bill records with due day, expected amount, category, notes, autopay details, optional APR, and flexible billing cycles (monthly, weekly, biweekly, quarterly, annual) -- bill history ranges for tracking which months a bill was active -- monthly tracker with payments, skipped bills, actual monthly amounts, and notes -- monthly income tracking and starting cash amounts (1st/15th/other) -- calendar view for due dates and payments -- analytics for monthly spending, expected vs actual totals, category spend, and payment history -- categories, profile, display name, notification preferences, password changes, and data tools -- admin user management, authentication settings, auth-mode/OIDC configuration, backups, scheduled backups, cleanup, migration rollback, audit logging, and status checks +Good fit: -## Features +- Home servers, NAS boxes, small VPS deployments, Portainer, or Docker Compose +- Single-user or multi-user households +- People who split monthly cash around the 1st and 15th +- Users who want import/export and database backup control +- Authentik/OIDC users who want optional SSO -- Tracker for month-by-month bill status, payment entry, notes, skipped bills, overdue totals, and month navigation -- Bills page for creating, editing, deactivating, reactivating, deleting, and controlling inactive bill history -- Calendar page with a monthly grid, bill due dates, payments, and progress summary -- Analytics page with date range, category/bill filters, charts, heatmap, and print output -- User-owned categories -- Settings for theme, currency, date format, and grace period -- Profile page with display name, notification preferences, password change, imports, exports, and import history -- User exports to Excel workbook or BillTracker user SQLite export (note: exports currently omit `cycle_type`, `cycle_day`, and `bill_history_ranges`) -- XLSX spreadsheet import with preview and import decisions -- User SQLite import from exports created by this app -- Admin users, role management, password resets, full database backups/restores, scheduled backups, cleanup, auth-mode/OIDC configuration, migration rollback, audit logging, and status page -- Local username/password login and optional authentik/OIDC login -- CSRF protection using double-submit cookie pattern with per-request nonces +Not a full replacement for: -## Quick Start +- Double-entry accounting +- Bank syncing +- Investment tracking +- Tax software + +## Quick Start With Docker + +The included Compose file runs the published image on host port `3030` and stores all persistent app data under `/data` inside the container. + +```bash +docker compose up -d +``` + +Open: + +```text +http://localhost:3030 +``` + +On first start, seed an admin account with: + +```yaml +environment: + INIT_ADMIN_USER: admin + INIT_ADMIN_PASS: change-this-password +``` + +Optional regular user seed: + +```yaml +environment: + INIT_REGULAR_USER: regularuser + INIT_REGULAR_PASS: changeme123 +``` + +Passwords must be at least 8 characters. Remove or rotate first-run seed values after initial setup. + +### Persistent Data + +For Docker, keep `/data` mounted. The container defaults to: + +```text +DB_PATH=/data/db/bills.db +BACKUP_PATH=/data/backups +``` + +Back up the mounted `/data` directory like you would any other sensitive financial data. + +## Node Install Install dependencies: @@ -58,69 +106,121 @@ Install dependencies: npm install ``` -Run the API and Vite frontend for development: +Run API and Vite UI for development: ```bash npm run dev ``` -Build the frontend: +Build and start production: ```bash npm run build -``` - -Start the production server: - -```bash npm start ``` The production server serves `dist/` and listens on `PORT`, defaulting to `3000`. -Useful scripts present in this repo: +Useful scripts: ```bash npm run dev:api npm run dev:ui npm run build +npm run check npm start -node scripts/test-import.js -node scripts/test-oidc-smoke.js -node scripts/test-cookie-options.js ``` -## Docker +`npm run check` runs backend CommonJS syntax checks and a Vite production build. -Docker files are included. The compose file runs the published image on host port `3030` and stores app data under `/data` in the container. +## Product Map -```bash -docker compose up -d -``` +### Tracker -On first start without an existing database, create the admin account with: +The Tracker is the main monthly view. It shows active bills for the selected month, grouped into: -```bash -INIT_ADMIN_USER=admin -INIT_ADMIN_PASS=change-this-password -``` +- `1st-14th` +- `15th-31st` -To also seed a regular (non-admin) user: +You can record payments, quick-pay bills, skip a bill for the month, add monthly notes, override monthly amounts, and navigate between months. The summary cards show starting cash, total paid, active period balance, overdue amount, previous month paid, and trend. -```bash -INIT_REGULAR_USER=regularuser -INIT_REGULAR_PASS=changeme123 -``` +### Bills -The regular user password must be at least 8 characters. Seeded users skip the first-login and password-change gates. +Bills store the recurring source data: -Remove or change those first-run values after the initial accounts exist. +- name, expected amount, due day, category +- active/inactive state +- billing cycle +- autopay and 2FA markers +- notes and account details +- optional debt fields such as balance, APR, and minimum payment +- inactive bill history ranges + +### Debt Snowball + +The Snowball page focuses on debt payoff planning: + +- snowball and avalanche ordering +- minimum-only baseline +- live payoff projections +- APR snapshots +- amortization schedules +- drag ordering and debt exclusion + +### Calendar, Summary, And Analytics + +- Calendar shows due dates, payments, and month progress. +- Summary handles income, starting amounts, and monthly planning. +- Analytics provides spending trends, category views, bill history, filters, heatmaps, and print output. + +### Data Tools + +BillTracker includes: + +- XLSX spreadsheet import with preview +- import by bill +- user SQLite import/export +- Excel workbook export +- import history +- admin database backup, restore, download, cleanup, and retention tools + +## Privacy Model + +BillTracker is intended to run privately in your own environment. + +- Bill data stays in your SQLite database. +- The app does not use third-party analytics, advertising, or telemetry. +- The public Privacy page explains the app’s local-first behavior. +- Login device details shown in Profile are visible to that user in the app UI, not exposed through the Admin UI. +- Optional update checks are for software update availability, not bill-data collection. + +Admins can manage users, reset passwords, configure authentication, and manage backups, but normal bill data is scoped to the signed-in user. + +## Authentication + +BillTracker supports local username/password login by default. Admins can create users, reset passwords, promote/demote users, and activate/deactivate accounts. + +Optional authentik/OIDC login can be enabled from Admin. OIDC uses authorization code flow with PKCE, state and nonce validation, and `openid-client` token validation. + +Important behavior: + +- Admin role is never granted by default through OIDC. +- OIDC admin access requires a configured admin group. +- Local login cannot be disabled unless OIDC is configured, enabled, and mapped to an admin group. +- The default seeded admin is restricted to admin routes and cannot access personal tracker data. + +See [Authentik-Integration.md](docs/Authentik-Integration.md) for setup details. ## Configuration -Most app settings are configured in the web UI. User-facing settings live under Settings/Profile. Server-wide settings such as users, backups, cleanup, and authentication methods live in Admin. +Most settings are configured in the web UI: -Real environment variables used by the app: +- User settings: Settings/Profile +- Server settings: Admin +- Authentication settings: Admin +- Backup and cleanup settings: Admin + +Common environment variables: ```bash PORT=3000 @@ -141,11 +241,11 @@ CSRF_SECURE=true CSRF_COOKIE_NAME=bt_csrf_token ``` -OIDC environment fallback variables are supported when the matching Admin database setting is blank: +OIDC fallback environment variables are used when matching Admin database settings are blank: ```bash OIDC_PROVIDER_NAME=authentik -OIDC_ISSUER_URL=https://yourURL.com/application/o/bills/.well-known/openid-configuration +OIDC_ISSUER_URL=https://auth.example.com/application/o/bills/.well-known/openid-configuration OIDC_CLIENT_ID= OIDC_CLIENT_SECRET= OIDC_TOKEN_AUTH_METHOD=client_secret_basic @@ -157,119 +257,50 @@ OIDC_AUTO_PROVISION=true Database-backed Admin settings take precedence over environment fallback values. -## Documentation +## Reverse Proxy And HTTPS -For detailed technical documentation, see the `docs/` directory: - -- **[CSRF-SPA-Setup.md](docs/CSRF-SPA-Setup.md)**: CSRF protection implementation for Single Page Applications, including the double-submit cookie pattern and environment configuration -- **[Authentik-Integration.md](docs/Authentik-Integration.md)**: Complete guide for Authentik OIDC integration, including setup, security features, and troubleshooting - -## Authentication - -BillTracker supports local username/password login by default. Admins can create users, reset user passwords, promote/demote users, and configure login methods. - -Optional authentik/OIDC login can be enabled in Admin. OIDC uses authorization code flow with PKCE, state and nonce validation, and `openid-client` token validation. OIDC users can be auto-provisioned when enabled. - -Admin role is never granted by default through OIDC. Set an authentik admin group in BillTracker; only users whose OIDC `groups` claim includes that configured group become app admins. - -BillTracker enforces lockout checks: local login cannot be disabled unless OIDC is configured, enabled, and mapped to an admin group. This prevents accidental lockout where no login method is available. - -The default admin account (created by `INIT_ADMIN_USER`/`INIT_ADMIN_PASS`) is restricted to admin routes only. It cannot access user tracker routes (bills, payments, calendar, etc.). Regular users and promoted admins have full access. - -## authentik Setup - -See **[Authentik-Integration.md](docs/Authentik-Integration.md)** for comprehensive setup instructions, including: - -- Detailed Authentik provider/application configuration steps -- PKCE and state parameter security -- ID token verification details -- User provisioning and group-to-role mapping -- Troubleshooting guide - -In authentik, create an OAuth2/OpenID provider/application for BillTracker: - -- Client type: confidential -- Redirect URI: `https://bills.example.com/api/auth/oidc/callback` -- Scopes: `openid email profile groups` -- Groups claim: make sure authentik sends `groups` -- Admin group: create or choose the authentik group that should become BillTracker admins - -In BillTracker, go to Admin -> Authentication Methods and set: - -- Provider name: `authentik` -- Issuer/discovery URL: `https://yourURL.com/application/o/bills/.well-known/openid-configuration` -- Client ID and client secret from authentik -- Redirect URI matching the authentik allowed redirect URI -- Scopes: `openid email profile groups` -- Admin group: the exact authentik group name for BillTracker admins -- Auto-provision users: enabled if you want valid authentik users created on first login - -The backend accepts either the provider issuer base URL or the full discovery URL. For authentik, the full discovery URL example is: +Run BillTracker behind HTTPS for normal use. If TLS terminates at a reverse proxy, forward: ```text -https://yourURL.com/application/o/bills/.well-known/openid-configuration +X-Forwarded-Proto: https ``` -Keep local login enabled until you have tested authentik login with an admin-group user. +Recommended production posture: -## Data, Imports, Exports, And Backups +```bash +HTTPS=true +COOKIE_SECURE=true +CSRF_SECURE=true +CSRF_SAME_SITE=strict +``` -BillTracker stores data in SQLite. By default the database is `db/bills.db`; set `DB_PATH` for a different location. In Docker, the image sets `DB_PATH=/data/db/bills.db` and `BACKUP_PATH=/data/backups`. +For plain HTTP development only, you may need: -User data is scoped to the signed-in user. User exports include bills, categories, payments, monthly bill state, notes, and export metadata. They do not include password hashes, sessions, admin settings, SMTP credentials, backup files, server paths, or other users' data. +```bash +CSRF_SECURE=false +COOKIE_SECURE=false +``` -Data tools: - -- XLSX spreadsheet import with preview before apply -- user SQLite import from BillTracker user exports -- user SQLite export -- Excel workbook export -- import history -- admin full database backup, import, download, restore, delete, scheduled backups, and retention - -Backups and exports contain sensitive financial data. The code writes SQLite backup files with restrictive file permissions, but backup/export encryption is not implemented. Protect downloaded files and backup storage yourself. +Leave `CORS_ORIGIN` unset for normal same-origin deployments. Set it only if the frontend and backend are intentionally served from different origins. ## Security Notes - Auth is required for user data routes. - Admin routes require an admin session. -- The default admin account cannot access user tracker routes. -- User-owned bill, category, payment, import, and export routes derive ownership from the authenticated session (`req.user.id` in SQL). -- CSRF protection uses a double-submit cookie pattern: a `bt_csrf_token` cookie is set on responses, and mutating requests must include a matching `x-csrf-token` header. The SPA reads this cookie with `document.cookie`, so `CSRF_HTTP_ONLY` defaults to `false`; do not set it to `true` unless token delivery changes. `sameSite=strict` and secure cookies remain the default posture. -- Local login, password change, import, export, admin actions, and OIDC routes have per-IP in-memory rate limits. -- CORS is disabled unless `CORS_ORIGIN` is set. -- Security headers include Content-Security-Policy with per-request nonces, plus standard hardening headers. HSTS is sent only when `HTTPS=true`. -- Session cookies are `httpOnly`, `sameSite=strict`, and marked secure when `COOKIE_SECURE=true`, `HTTPS=true`, or the request appears to be HTTPS. -- Password changes rotate the current session ID and invalidate all other sessions. -- Audit logging records security-sensitive events: login, logout, password changes, role changes, CSRF failures, and migration operations. -- OIDC validation is handled through `openid-client` using discovered provider metadata and JWKS. -- Protect database files, backups, and exports as sensitive financial records. +- User-owned bill, category, payment, import, export, and settings routes derive ownership from the authenticated session. +- CSRF uses a double-submit cookie pattern. The SPA reads `bt_csrf_token` with `document.cookie` and sends it as `x-csrf-token` on mutating requests. +- Do not set `CSRF_HTTP_ONLY=true` for this SPA unless token delivery changes. +- Session cookies are HTTP-only and SameSite-protected. +- Password changes rotate the current session and invalidate other sessions. +- Rate limits protect local login, password changes, imports, exports, admin actions, and OIDC routes. +- Security headers include CSP nonces and standard hardening headers. +- Audit logging records security-sensitive events such as login, logout, password changes, role changes, CSRF failures, and migration operations. -## Reverse Proxy And HTTPS - -Run BillTracker behind HTTPS for normal use. If TLS terminates at a reverse proxy, forward `X-Forwarded-Proto: https` so secure-cookie detection can work. You can also set `HTTPS=true` or `COOKIE_SECURE=true`. - -Set `CORS_ORIGIN` only when the frontend and backend are served from different origins. For the normal same-origin deployment, leave it unset. - -## Project Structure - -```text -client/ React app, pages, layout, UI components -db/ SQLite connection, schema, startup migrations -middleware/ auth checks, CSRF, rate limits, security headers -routes/ Express API routes -services/ auth, OIDC, backups, scheduler, imports, cleanup, status, notifications, audit -workers/ daily background tasks (notifications, cleanup) -setup/ first-run admin setup -scripts/ DB migrations, seed data, and smoke/import tests -public/ legacy static assets -img/ app-runtime images and source screenshots -docs/ Engineering Reference Manual, CSRF guide, Authentik integration -``` +Backups and exports can contain sensitive financial data. The app writes SQLite backup files with restrictive permissions, but backup/export encryption is not implemented. Protect downloaded files and mounted volumes yourself. ## Upgrading -For a direct Node install: +For a Node install: ```bash git pull @@ -278,18 +309,52 @@ npm run build npm start ``` -Restart your process manager after building. The app initializes the SQLite schema and runs additive migrations on startup; the Docker entrypoint also runs `scripts/migrate-db.js` before starting unless `RUN_DB_MIGRATIONS=false`. +Restart your process manager after building. -For Docker, pull/rebuild the image, recreate the container, and keep the `/data` volume mounted. +For Docker: + +```bash +docker compose pull +docker compose up -d +``` + +If you build locally, rebuild the image and recreate the container. + +The app initializes the schema and runs additive migrations on startup. The Docker entrypoint also runs `scripts/migrate-db.js` before starting unless: + +```bash +RUN_DB_MIGRATIONS=false +``` + +## Project Structure + +```text +client/ React app, pages, layout, UI components +db/ SQLite connection, schema, startup migrations +middleware/ auth checks, CSRF, rate limits, security headers +routes/ Express API routes +services/ auth, OIDC, backups, imports, cleanup, status, audit logic +workers/ background tasks +setup/ first-run admin setup +scripts/ migrations, seed data, smoke/import tests +docs/ technical references and integration guides +``` + +## Documentation + +- [HISTORY.md](HISTORY.md): release history +- [CSRF-SPA-Setup.md](docs/CSRF-SPA-Setup.md): CSRF behavior for the SPA +- [Authentik-Integration.md](docs/Authentik-Integration.md): authentik/OIDC setup +- [Engineering_Reference_Manual.md](docs/Engineering_Reference_Manual.md): deeper implementation reference ## Known Limitations - Admin backups and user exports are not encrypted by the app. +- Bank sync is not implemented. - OIDC single logout is not implemented. -- User exports (Excel and SQLite) currently omit `cycle_type`, `cycle_day`, and `bill_history_ranges` data. - Rate limiting is in-memory, so counters reset on restart and are not shared across multiple app instances. -- Authentik live login must be tested in your deployment with your authentik provider. -- The XLSX parser dependency has known upstream security advisories; the import route is authenticated, file-size limited, and parses cells as data. +- Multiple OIDC providers are not currently supported. +- The XLSX parser dependency has known upstream security advisories; import routes are authenticated, file-size limited, and parse spreadsheet cells as data. ## License