Commit Graph

51 Commits

Author SHA1 Message Date
null c43c476ae9 fix: subscription recommendation dedup and amount-bucket grouping
- Amount-bucket grouping ensures consistent charges are grouped together
- Catalog lookup names and boosts the result
- Deduplication ensures one recommendation per known service
- Removed catalog-first rewrite
2026-05-29 02:51:30 -05:00
null 1d8ae4f511 fix: sync_days hard-clamped to 90 (SimpleFIN Bridge limit)
- bankSyncConfigService: SYNC_DAYS_MAX=90, getBankSyncConfig clamps on read,
  setSyncDays rejects >90 with explanation
- bankSyncService: every sync requests full sync_days window, dedup handles
  already-seen transactions
- dataSources status endpoint returns sync_days alongside enabled
- BankSyncAdminCard: input max 90, live clamp, description cites Bridge limit
- BankSyncSection: third stat tile showing History window X days
2026-05-29 02:23:19 -05:00
null 7682758aa8 fix: sync_days now reads from DB config, admin UI controls it
- bankSyncService: removed local syncDaysBack() reading env directly;
  sinceEpoch() now calls getBankSyncConfig().sync_days
- bankSyncConfigService: added setSyncDays() with 1-730 day validation
- routes/admin: PUT accepts sync_days alongside enabled/sync_interval_hours
- BankSyncAdminCard: Transaction history days input, loaded from config,
  defaults 90, dirty-checked on save
2026-05-29 01:33:54 -05:00
null 262d7789db feat: account monitoring, expanded sync UI, match filtering, error toasts
Backend:
- v0.64 migration: monitored column on financial_accounts
- GET/PUT data-sources accounts endpoints for monitored toggle + tx listing
- matchSuggestionService: excludes unmonitored accounts from match scoring

Frontend:
- BankSyncSection rebuild: accounts panel with monitored switch, expand for
  last 50 transactions, match status badges, optimistic toggle
- TransactionMatchingSection: toast on bills load failure
- DataPage: toast on import history load failure
- ProfilePage: toast on both login history fetch failures
2026-05-29 01:06:20 -05:00
null 542ab5e382 feat: configurable sync interval, auto-match, encryption note, admin link, SimpleFIN hyperlink
#1 Sync interval in admin UI:
- bankSyncConfigService: reads simplefin_sync_interval_hours from settings
  (DB-first, env fallback, default 4h), setSyncIntervalHours() with validation
- bankSyncWorker: live-updates interval from getBankSyncConfig() each tick
- routes/admin: PUT accepts enabled and sync_interval_hours independently
- BankSyncAdminCard: number input (0.5 step, 0.5-168 range), dirty-checks both

#3 Auto-match after background sync:
- matchSuggestionService: autoMatchForUser() auto-applies suggestions ≥80
  score (exact amount + date ±1d + name signal), lazy-requires matchTransactionToBill
- bankSyncWorker: calls autoMatchForUser after each successful sync, own try/catch

#4 Encryption note in BankSyncAdminCard below worker status panel

Also: error handling, admin link in tracker sidebar, SimpleFIN bridge hyperlink
2026-05-29 00:28:50 -05:00
null 7a58d69c70 feat: hybrid subscription tracker
Added subscription metadata to bills: is_subscription, type, reminder_days, source, detected_at
Backend subscription API (routes/subscriptions.js)
SimpleFIN recommendation logic (services/subscriptionService.js)
New /subscriptions page (client/pages/SubscriptionsPage.jsx)
Track-as-subscription controls in BillModal.jsx
Navigation under Tracker menu
Accepting a recommendation creates a subscription-backed bill + links detected transactions
2026-05-28 22:54:07 -05:00
null 22df64e5e7 feat: auto-sync worker for SimpleFIN bank sync
New:
  services/bankSyncWorker.js — interval-based worker running every 4h (configurable via SIMPLEFIN_SYNC_INTERVAL_HOURS)
    - Checks bank sync enabled, fetches oldest-synced sources, skips <1h old
    - Staggers syncs 3s apart, writes last_error on failure, timer.unref() for clean shutdown

Modified:
  server.js — starts worker inside app.listen callback
  routes/admin.js — GET bank-sync-config includes worker status (running, interval, last/next run)
  client/components/admin/BankSyncAdminCard.jsx — shows auto-sync worker status panel when enabled
  .env.example — SIMPLEFIN_SYNC_INTERVAL_HOURS
2026-05-28 22:32:33 -05:00
null 88a4b64924 feat: DB-first bank sync config, admin toggle, extracted BankSyncSection
New:
  services/bankSyncConfigService.js — bank_sync_enabled from settings table, env fallback
  client/components/admin/BankSyncAdminCard.jsx — single toggle + encryption key status
  client/components/data/BankSyncSection.jsx — full connection management extracted from SettingsPage

Modified:
  routes/dataSources.js — per-request getBankSyncConfig() instead of module-level env check
  routes/admin.js — GET/PUT /api/admin/bank-sync-config
  AdminPage.jsx — renders BankSyncAdminCard after EmailNotifCard
  SettingsPage.jsx — BankSyncSection removed, 580->352 lines
  DataPage.jsx — BankSyncSection first, passes simplefinConn to TransactionMatchingSection
  TransactionMatchingSection.jsx — compact sync bar with green dot + Sync Now
  Layout.jsx — SimplefinBadge shows muted dot when enabled
  client/api.js — bankSyncConfig API calls
2026-05-28 22:06:15 -05:00
null 42abb12497 feat: SimpleFin bank sync with encrypted token storage
New services:
  services/encryptionService.js — AES-256-GCM with SHA-256 derived key
  services/simplefinService.js — protocol layer: claim token, fetch accounts/transactions, normalize to DB shapes
  services/bankSyncService.js — orchestration: connect, sync, disconnect with encrypted access URL storage

Modified:
  routes/dataSources.js — status, connect, sync, disconnect endpoints (gate on BANK_SYNC_ENABLED=true)
  client/api.js — simplefinStatus, connectSimplefin, syncDataSource, deleteDataSource, dataSources
  client/pages/SettingsPage.jsx — BankSyncSection with connected account info, sync/disconnect actions, setup token input
  .env.example — BANK_SYNC_ENABLED, TOKEN_ENCRYPTION_KEY, SIMPLEFIN_APP_NAME
2026-05-28 21:30:20 -05:00
null 8cab248959 security fixes 2026-05-28 03:59:35 -05:00
null 55837b8b25 docs: update engineering reference manual to v0.28.01
- Add sections 5.15-5.21 (Data Sources, Transactions, CSV Import, Match Suggestions)
- Add v0.47-v0.64 migrations to database reference
- Add data_sources, financial_accounts, transactions table schemas
- Add payment_source and transaction_id to payments table
- Update version header to 0.28.01, date to 2026-05-16
- Fix section numbering
2026-05-16 21:41:13 -05:00
null 060c8dc2f4 chore: version bump to 0.28.01 and update HISTORY format 2026-05-16 21:36:04 -05:00
null 9d933f70cc v0.28.01 2026-05-16 20:26:09 -05:00
null b124e48ebc v0.28.0 2026-05-16 15:38:28 -05:00
null 53670b3745 v0.28.0 2026-05-16 11:42:32 -05:00
null 88c1374d97 v028.0 2026-05-16 10:56:56 -05:00
null 59d9d21d4c v0.28.0 2026-05-16 10:34:32 -05:00
null 9174ec3290 v0.28. 2026-05-16 10:17:24 -05:00
null 0ba315bd32 v0.28.0 2026-05-15 22:45:38 -05:00
null 263f1c5e6e v0.27.04 2026-05-15 01:36:56 -05:00
null 576163e85b apr/snowball 0.27.04 2026-05-15 00:03:32 -05:00
null d720931894 v0.27.02 push 2026-05-14 21:00:07 -05:00
null eea5641126 snowball visuals 2026-05-14 19:33:23 -05:00
null 440f872d97 snowball bug fixes 2026-05-14 03:00:01 -05:00
null 7d2d0bf45e 0.28.0 snowball release 2026-05-14 02:11:54 -05:00
null 48fe87ea25 corrections 2026-05-14 01:17:05 -05:00
null 2ce5328fd2 v0.25.0: roadmap redesign, import CSRF fix, AdminDashboard removed
- RoadmapPage: kanban-style priority lanes, shadcn Collapsible/Tabs,
  lazy-loaded activity log, admin-only /api/about/roadmap + /dev-log endpoints
- Import CSRF fix: added x-csrf-token header to importAdminBackup,
  previewSpreadsheetImport, previewUserDbImport raw fetch() calls
- Removed AdminDashboard.jsx, replaced by RoadmapPage
- Added @radix-ui/react-collapsible + collapsible shadcn component
- Security audit by Private_Hudson: PASS (CSRF fix verified,
  admin endpoints gated, path traversal mitigated, XSS safe)
2026-05-11 21:42:36 -05:00
null 98ede20cd3 fix: prevent duplicate payment prompts 2026-05-11 16:04:21 -05:00
null b29d3a0b02 fix: starting amounts paid_from_other calculation + pay badge alignment on tracker 2026-05-11 15:00:35 -05:00
null 24b4e8d24e refactor: extract bills.js business logic into services/billsService.js (Phase 1) 2026-05-11 12:12:31 -05:00
null c1ac14efe3 v0.24.4: analytics mobile layout + previous month payment toggle 2026-05-11 11:56:49 -05:00
null 80b3bcc17b fix: HIGH+MEDIUM batch — 10 fixes (v0.24.0)
HIGH:
- Admin toggle-paid: removed cross-user admin branch, now requires ownership
- Analytics crash: imported missing standardizeError
- Export data loss: added cycle_type, cycle_day, bill_history_ranges to exports
- Single-user lockout: removed unnecessary sessions join from getSingleModeUser

MEDIUM:
- Password rate limiter: scoped to change-password only, not all profile routes
- Profile session invalidation: fixed req.sessionId → req.cookies[COOKIE_NAME]
- CSRF default: httpOnly now defaults to false (matches SPA double-submit pattern)
- CSRF password routes: removed csrfSkip for password change endpoints
- Notification due-day: calendar day comparison instead of timestamp floor
- Upcoming bills: clamped days to 1-365, default 30 for invalid input

FUTURE.md: marked all 10 items as FIXED, bumped version refs
HISTORY.md: added v0.24.0 entry
2026-05-10 15:25:47 -05:00
null 5537ab2bd5 fix: clear demo data button, seed user ID bug, duplicate endpoint (v0.23.4)
- DataPage: removed 'coming soon' placeholder, made Clear Demo Data button accessible from seeded state
- seedDemoData.js: fixed userId -> targetUserId bug
- settings.js: removed duplicate /api/settings/seed-demo-data endpoint
- Version bumped to 0.23.4
2026-05-10 15:11:02 -05:00
null 78f95f784e fix: remove duplicate login route (authLogin.js), consolidate into auth.js
- Deleted routes/authLogin.js (orphaned duplicate login handler)
- Removed authLoginRouter import and mount from server.js
- Rate limiter now runs as standalone middleware on /api/auth/login
- Added try/catch to auth.js login handler (was only in deleted file)
- Consistent audit log variable naming (username vs req.body.username)
- No functionality change — login flow works identically
2026-05-10 12:20:50 -05:00
null 52db06001f v0.23.1: migration rollback capability
- Add rollbackMigration() function in db/database.js with transaction safety
- Add POST /api/admin/migrations/rollback endpoint (admin-only)
- Rollback SQL for v0.44 (indexes), v0.45 (audit_log table), v0.46 (cycle columns)
- Error codes: NOT_APPLIED (404), ROLLBACK_NOT_SUPPORTED (422)
- Audit logging for rollback events
- Fix duplicate migrationStartTime declaration from v0.23.0 commit
- Fix broken migration completion audit log from v0.23.0 commit
- Fix DB path exposure (uses path.basename() now)
2026-05-10 10:44:39 -05:00
null c4a3593241 v0.22.2: Session Token Rotation on Auth Events
- invalidateOtherSessions() in authService.js: deletes all sessions except current
- Password change (auth.js + profile.js) now invalidates all other sessions
- Password change rotates current session ID (sets new cookie)
- New POST /api/auth/logout-all endpoint (deletes all sessions + clears cookie)
- Audit logging for logout.all and password.change
- Added last_password_change_at to auth.js change-password for consistency
- Hudson security audit: 6/6 PASS
2026-05-10 03:55:14 -05:00
null 65849fc554 v0.22.1: N+1 Query Optimization
- Batch queries replace per-bill loops in tracker and analytics
- monthly_bill_state, payments, prev month payments batched with WHERE IN
- Empty billIds guards prevent SQL errors
- Hudson security audit: 5/5 PASS (SQL injection, empty IN, user scoping, data leakage, type safety)
2026-05-10 03:29:09 -05:00
null cfb074c7cd v0.21.0: 3-Month Trend Indicator on Tracker
- Backend: 3-month payment aggregation with year-wrapping, trend object in API (direction, percent_change, 3_month_avg)
- Frontend: TrendIndicator component (arrow + percentage + label), TrendCard with purple gradient
- Bug fix: Bishop fixed 3-month query to JOIN through bills for user scoping (payments table has no user_id)
- Bug fix: Ripley removed duplicate TrendIndicator function definition
- Hudson security audit: 5/5 PASS (SQL injection, user scoping, date wrapping, division by zero, XSS)
2026-05-10 01:22:51 -05:00
null 4990bf47f6 v0.20.9: Previous Month Paid column on Tracker
- Backend: previous month calculation with year wrapping (Jan→Dec)
- Backend: previous_month_paid per bill row, previous_month_total in summary
- Frontend: 'Last Month' column in desktop table with muted text
- Frontend: 'Last Month' in mobile view, summary card for prev month total
- Hudson security audit: 5/5 PASS (SQL injection, date wrapping, user scoping, auth, XSS)
2026-05-10 00:52:23 -05:00
null bd796d61c0 v0.20.8: Billing cycle sub-categories + server-side cycle_day validation
- Migration v0.46: cycle_type (monthly/weekly/biweekly/quarterly/annual) and cycle_day columns
- Server-side validation: cycle_type whitelist, cycle_day validated per type
  - monthly: 1-31 integer
  - weekly/biweekly: day name enum
  - quarterly/annual: free text (max 50 chars)
- BillModal UI: conditional cycle_day selector (ordinal/weekday/text)
- Hudson audit: 4/5 PASS, fixed medium-risk cycle_day validation gap
2026-05-10 00:39:11 -05:00
null 7503a54f81 v0.20.6: Audit logging for critical operations
- New audit_log table (migration v0.45) with indexes
- logAudit() service with try/catch safety (never crashes app)
- Audit events: login.success, login.failure, logout, password.change, role.change, csrf.failure, profile.update, profile.settings.update
- All events include ip_address and user_agent
- No passwords, tokens, or session IDs logged
- Hudson security audit: 7/7 PASS
2026-05-10 00:03:12 -05:00
null 8e7f977fef v0.20.5: Bulk payment input validation
- Request body must contain `payments` array (breaking change from raw array)
- Max 50 items per bulk request
- Per-item validation: bill_id (integer regex + parseInt), paid_date (YYYY-MM-DD), amount (finite number >= 0)
- Duplicate detection using bill_id + paid_date + amount composite key — skipped, not rejected
- Response format: { created, skipped, errors }
- Security fix: bill_id type coercion attack (parseInt('1abc') bypass) blocked via regex check
- Security fix: Infinity amount bypass blocked via isFinite() check
- Hudson audit: 5/7 PASS, 2 FAIL fixed (type coercion + Infinity)
2026-05-09 23:41:28 -05:00
null 0cd8423a19 v0.20.1: code splitting, version badge on roadmap, roadmap nav link
- React.lazy + Suspense for all page components (except LoginPage)
- PageLoader component for loading states
- Version badge on admin roadmap page
- Version in /api/about-admin response
- Roadmap nav link for admins (dropdown + sidebar)
- /admin/roadmap route
2026-05-09 22:01:19 -05:00
null a9cdf846fe v0.19.2: fix legacy DB migration login failure + security hardening
CRITICAL fix: Users upgrading from pre-migration-tracking databases
(now get 'invalid username/password' because schema_migrations table
doesn't exist. Added handleLegacyDatabase() and
reconcileLegacyMigrations() to detect and reconcile legacy DBs.

Security fixes:
- Path traversal: replaced sanitizePath() with ALLOWED_FILES allowlist
- Public /about bypass: added admin route guard in App.jsx
- Sensitive info exposure: expanded redactSensitiveContent() patterns
- Error message path leaks: generic error messages only
- Race condition: wrapped in db.transaction() in server.js
- Password validation: INIT_REGULAR_PASS min 8 chars with process.exit(1)

All verified by Bishop (build + runtime) and Private_Hudson (security).
2026-05-09 18:25:25 -05:00
null 6c7d481494 feat: add admin about page with security hardening
- Add /api/about-admin endpoint (admin-only, path traversal protection, content redaction, error sanitization)
- Add /admin/about route with RequireAuth admin guard
- Add adminActionLimiter rate limiting on about-admin endpoint
- Add rehype-sanitize XSS prevention in AboutPage.jsx
- Add aboutAdmin API client endpoint
- Create HISTORY.md with version bump convention (patch/minor/major)
- Update Engineering Reference Manual with about-admin docs and security measures
- Add INIT_REGULAR_USER/INIT_REGULAR_PASS env vars to docs
- Update FUTURE.md with critical regular user env var item
2026-05-09 16:25:12 -05:00
kaspa 4d1709aea3 push 2026-05-09 13:03:36 -05:00
_null 3228332e8c push 2026-05-04 23:34:24 -05:00
_null d1efeece04 push 2026-05-04 20:12:57 -05:00
_null b019487423 init 2026-05-04 16:38:03 -05:00
_null 969139251d calendar 2026-05-04 13:14:32 -05:00