Commit Graph

58 Commits

Author SHA1 Message Date
null 3978507572 feat(tracker): overdue command center with snooze/skip/pay + sidebar badge
- migration v0.70 adds snoozed_until TEXT to monthly_bill_state
- trackerService: snoozed_until in monthly state fetch + getOverdueCount()
- GET /api/tracker/overdue-count endpoint
- PUT /bills/:id/monthly-state validates snoozed_until
- OverdueCommandCenter component: collapsible, per-bill actions, hides snoozed
- useOverdueCount hook (2-min stale, 5-min poll, tab-only)
- Sidebar/nav uses overdue count badge on Tracker menu item
- Bump v0.33.8.7 → v0.34.0
2026-05-30 13:19:09 -05:00
null 6b0c86b73c revert: compact tracker mode + wider layout, keep S badge + remaining/Done header (batch 0.33.8.7)
- Removed hasBoth, compact prop, 2xl:min-w-[700px], 2xl:hidden Last Month,
  narrowed columns — back to original single-column tracker layout
- Removed 2xl:max-w-[2000px] from Layout/Sidebar/AdminShell/footer/nav
- Kept S badge in all 4 locations and bucket remaining/Done header
- Added mkdocs/ to .gitignore
- Bump v0.33.8.6 -> v0.33.8.7
2026-05-29 21:16:13 -05:00
null af601057c4 style: wider max-width at 2xl+ (1500px -> 2000px) (batch 0.33.8.6)
- Layout, AdminShell, Sidebar, footer, mobile nav: 2xl:max-w-[2000px]
- Content area grows from ~1436px to ~1936px, enough room for
  dual-bucket tracker at 2xl+
- Bump v0.33.8.5 -> v0.33.8.6
2026-05-29 20:40:14 -05:00
null f99cd82438 feat: compact tracker, S badge, side-by-side buckets (batch 0.33.8.5)
- Sub badge changed to 'S' in all 4 locations with matching border style
- Two-bucket grid at 2xl+ when both buckets have bills
- Compact mode: narrow table, hide Last Month column, shrink Notes/Actions/Due
- Bucket header shows remaining/Done labels alongside paid/total/overpaid
- Removed standalone Remaining summary card (redundant with bucket header)
- Row and Bucket accept compact=false
- Bump v0.33.8.4 -> v0.33.8.5
2026-05-29 20:33:01 -05:00
null a15436b637 feat: 90-day backfill + auto-seed + status page redesign (batch 0.33.8.4)
- New backfillDataSource export and POST route for 89-day history pull
- Auto-seed 89 days on first connect, 30 days for routine syncs
- sinceEpoch() replaced with sinceEpochDays(days) with explicit param
- Status page errorRow now filters AND status = 'error'
- Full status page redesign: colored top borders, card icons, section labels,
  health banner with glowing dot, consistent spacing
- Bump v0.33.8.3 -> v0.33.8.4
2026-05-29 19:58:52 -05:00
null 0f9f48e255 feat: subscription badges + status improvements + dailyWorker fix (batch 0.33.8.3)
- Sub badge (indigo) in all 4 locations, toggleable in Bills prefs
- SimpleFIN Sync card on Status page
- dailyWorker.start() now called on startup
- tracker.overdue_count uses real SQL query
- Status page accuracy: dynamic headers, Degraded state, worker last_error check
- Removed SimpleFIN prefix from Recommendations title
- Bump v0.33.8.2 -> v0.33.8.3
2026-05-29 19:21:46 -05:00
null b34e21d1ba feat: advisory non-bill transaction filter system (batch 0.33.8.0)
- Migration v0.68: seeds advisory_non_bill_filters (5k+ patterns) and
  advisory_bill_like_overrides (83 override terms) on first startup.
  Idempotent — skips if already seeded.
- advisoryFilterService.js: lazy in-memory cache checks override terms
  first, then scans patterns. Returns null | {confidence, category, rationale}.
- Transaction list: each row gets advisory_filter from the server.
- High-confidence unmatched transactions: show 'Probably not a bill'
  italic text instead of 'No bill linked'.
- MatchBillDialog high confidence: 'Create Bill' replaced with
  'Probably not a bill · create anyway' text link for manual override.
- MatchBillDialog medium confidence: Create Bill button renders muted.
- Same logic in empty-state CTA when search returns no results.
- BillModal onSave now returns the saved bill so callers can auto-match.
- Bump v0.33.7.3 -> v0.33.8.0
2026-05-29 18:06:12 -05:00
null 392de3264f fix(ui): SimpleFIN transaction table fixed column sizing (batch 0.33.7.3)
- Table now uses table-fixed + colgroup for fixed column widths
- Long transaction text can no longer push action buttons off-screen
- Action buttons are compact icon-only with aria-label/title
- Long matched bill names are truncated with truncate class
- Bump v0.33.7.2 -> v0.33.7.3
2026-05-29 16:51:31 -05:00
null 32f1568515 feat: SimpleFIN payment backfill button on subscription bills (v0.33.7.2) 2026-05-29 04:19:20 -05:00
null 6b30ee4eb7 feat: merchant rules, auto-match on sync, duplicate API fix
- Removed duplicate unmatchTransaction API entry in api.js
- Unmonitored accounts: no chevron, click-to-expand disabled, tx panel hidden
- matched_bill_name included via LEFT JOIN bills in accounts query
- BillPickerDialog resets search/selection on open
- Link to bill: marks historical txs matched, stores merchant rule,
  applyMerchantRules catches other unmatched txs from same merchant
- Track (new subscription): creates bill with is_subscription=1, stores
  merchant rule for ongoing tracking
- SimpleFIN sync: applyMerchantRules runs after tx insert, auto-matches
  by merchant rule with payment_source='auto_match'
- Auto-match payments have transaction_id set, treated same as manual matches
- New services/billMerchantRuleService.js for rule storage and matching
- Migration for bill_merchant_rules table
2026-05-29 03:38:48 -05:00
null eeb26ccab1 feat: manual match/unmatch transactions to bills
Backend:
- POST /api/matches/confirm — atomic payment creation + transaction match
- POST /api/matches/:transactionId/unmatch — soft-delete payment, reset transaction
- Account transactions include matched_bill_id and matched_bill_name

Frontend:
- Unmatched transactions show + match pill button
- BillPickerDialog with transaction details + searchable bill list
- Confirm creates payment and updates row immediately
- Matched transactions show Unlink icon to remove match
- Toast on success with bill name and date
2026-05-29 03:02:36 -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 b03264ceb1 feat: zero-config encryption + SimpleFIN Bridge links
- encryptionService.js: getKey() tries TOKEN_ENCRYPTION_KEY env first, then
  auto-generates a random 48-byte key on first startup, persists to settings
  as _auto_encryption_key. assertEncryptionReady() is now a no-op.
- bankSyncConfigService.js: removed encryption_key_set response and
  encryptionKeyReady() helper. No env config required.
- .env.example: TOKEN_ENCRYPTION_KEY removed. Comment says enable from Admin
  panel, no env config required.
- BankSyncSection.jsx: added SimpleFIN Bridge links — 'Open SimpleFIN Bridge'
  for first-time setup, 'Get a SimpleFIN token' for existing connections
2026-05-29 00:04:28 -05:00
null 3fea3931f5 style: AP badge next to bill name instead of blue dot
Tracker and mobile tracker rows now show a small AP badge
immediately to the right of the bill name, replacing the
blue dot on the left.
2026-05-28 23:50:03 -05:00
null 792980b8ba style: stronger late/missed payment visibility
- Tracker rows, mobile rows: alert icons, left-edge marker, stronger row tinting
- Calendar grid and detail dialog: brighter dots, count badges
- StatusBadge: stronger orange/rose badges for late/missed
- Shared badge component: clearer contrast
2026-05-28 23:42:46 -05:00
null a1f679f7b0 style: global readability/theme pass
- Sharpened font stack in index.css, removed softer Georgia digit font for UI text/money
- Tuned dark-mode tokens: clearer foreground, brighter muted text, stronger borders, defined cards
- Updated UI primitives: cards, buttons, inputs, selects, tables, badges
- Cleaned up bills rows, mobile bill rows, tracker dismiss, snowball icons, summary/category/health/analytics money values, import/export status icons
- Reduced fuzzy uppercase label spacing globally
2026-05-28 23:18:14 -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 858f65b66b fix: BankSyncAdminCard toggle no longer gated on encryption key
- Removed disable logic and key warning banner from BankSyncAdminCard
- Toggle works freely regardless of TOKEN_ENCRYPTION_KEY status
- encryptionKeyReady and encryption_key_set left as informational only
2026-05-28 22:18:20 -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 979886cb6a style: CalendarPage readability pass + DataPage fix
CalendarPage.jsx:
- Tightened day numbers, due-count badges, bill labels inside cells
- Crisper color contrast for paid/due/missed states
- Cleaner grid surfaces and borders for row/day tracking
- Switched font-mono values to tracker-number style

SeedDemoDataSection.jsx:
- Fixed render logic for data page
2026-05-28 21:40:27 -05:00
null 71dfbe36cc refactor: component splits, PWA support, CommandPalette
Component Splits:
  - AdminPage.jsx: 1,906 -> 82 lines (logic moved to client/components/admin/ — 9 files)
  - DataPage.jsx: 3,132 -> 60 lines (logic moved to client/components/data/ — 8 files)
  - TrackerPage.jsx: 2,566 -> 2,132 lines (MonthlyStateDialog, StartingAmountsEditDialog, PaymentModal)

PWA:
  - vite-plugin-pwa installed with NetworkFirst caching for API routes
  - Square PWA icons (192x192, 512x512, apple-touch-icon)
  - theme-color, apple meta tags, touch icon in index.html
  - Build generates dist/sw.js + Workbox runtime

CommandPalette:
  - Navigation commands, Add bill action, month jumps
  - Grouped results with empty/filtered states
2026-05-28 20:53:22 -05:00
null 92cc667947 chore: bump version to v0.28.4.4 2026-05-28 20:14:00 -05:00
null 33e5c187a3 dark theme 2026-05-28 19:58:01 -05:00
null d99ea8057e dark theme 2026-05-28 19:40:55 -05:00
null 1f3a254c7c brighten dark mode 2026-05-28 19:30:46 -05:00
null 8f7d0aeaff styling 2026-05-28 04:06:37 -05:00
null 82de135186 push 2026-05-18 09:44:16 -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 88c1374d97 v028.0 2026-05-16 10:56:56 -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 d720931894 v0.27.02 push 2026-05-14 21:00:07 -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 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 890427c75a v0.24.3: Session fixes, activity log corrections, UI polish 2026-05-11 13:39:48 -05:00
null 314159d241 v0.21.1: Loading Skeletons & Async State
- Reusable Skeleton component (line, circle, card, button, input variants)
- TrackerPage: skeleton cards, rows, buckets with aria-busy attributes
- BillsPage: skeleton rows during loading
- Bug fix: double closing brace />}} on Bucket component
- Hudson security audit: 5/5 PASS
2026-05-10 01:35:41 -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 e184fed88a v0.20.7: Keyboard navigation and ARIA accessibility
- Skip-to-content link for keyboard users (sr-only/focus:not-sr-only pattern)
- aria-expanded and aria-haspopup on Tracker menu dropdown
- aria-label on footer, role='main' and aria-labelledby on layout wrapper
- Main content wrapped in <main> with unique id from React useId()
- Fixed build error: useId imported from react, not react-router-dom
- Hudson security audit: 5/5 PASS (no XSS, no DOM clobbering, no injection)
2026-05-10 00:18:36 -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 d8888af845 feat: add Roadmap nav link for admins
- Added Roadmap link in dropdown menu (below About), admin-only
- Added Roadmap in admin sidebar nav
- Added /admin/roadmap route pointing to AboutPage with admin prop
- Uses Map icon from lucide-react
2026-05-09 21:26:39 -05:00
null 852da29b4d v0.20.0: admin dashboard with roadmap and activity log
- New AdminDashboard component with Roadmap and Activity Log
- Color-coded priority cards (🔴🟠🟡🔵💭) with collapsible sections
- CRITICAL/HIGH expanded by default, others collapsed
- Activity log shows DEVELOPMENT_LOG entries in reverse chronological order
- Admin-only rendering, non-admins see standard About page
- Custom scrollbar styles for admin panels
- Version bumped to 0.20.0 (Bishop)
2026-05-09 21:14:21 -05:00
null 4e91bed343 v0.19.2: add React Error Boundaries for crash recovery
Added ErrorBoundary component wrapping all routes in App.jsx.
Shows friendly fallback UI with Try Again and Reload buttons
instead of white screen crash. Logs component stack to console.
2026-05-09 18:33:02 -05:00