Plaid ClientId/Secret are now stored per-user in the database
(encrypted) instead of in appsettings.json. Users enter their own
Plaid developer credentials in the Settings > Bank Connections tab.
- New BankSyncSettings model (1:1 with User) for encrypted credentials
- PlaidSyncProvider is now stateless, receives credentials per-call
- Settings UI shows a credentials card with save form
- Connect via Plaid button disabled until credentials are configured
- Removed Plaid section from appsettings.json
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Validate Plaid credentials are configured before calling the API,
and validate the returned link token before passing it to Plaid
Link JS. Show error snackbars for all bank sync failures instead
of only logging to console.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove nested AppLayout wrapper from SettingsView — the layout is
already applied at the App.vue level around router-view.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add automated transaction syncing via Plaid and SimpleFIN providers,
a Settings page for managing connections and account mappings,
background scheduled syncing, and sync history logging.
New backend: BankSync plugin project with PlaidSyncProvider and
SimpleFinSyncProvider, SyncConnection/LinkedAccount/SyncLog models,
AES-256 encryption service, BankSyncService orchestration,
BankSyncBackgroundService (15-min tick), and BankSyncController
(13 endpoints). EF migration creates sync_connections,
linked_accounts, and sync_logs tables.
New frontend: Settings view with 3 tabs (Profile, Bank Connections,
Sync History), bankSync API service, BankSyncComplete SignalR
notifications, and Settings nav item in sidebar + avatar dropdown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add full frontend UI for five backend features: bank reconciliation (3-step
stepper workflow), payee management (CRUD with alias chips), transaction splits
(expandable rows + split editor), plugins (card grid), and real-time SignalR
notifications (bell dropdown with badge). Fix backend PayeeResponse to expose
alias IDs for deletion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap each report API call in a fetchReport helper that catches errors
individually and returns null, treating 4xx responses as empty data
instead of surfacing an error message to the user.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add interactive reports dashboard with 4 chart types (spending by
category donut, income vs expense bar, net worth area, cash flow bar)
using ApexCharts, date range presets, and account filtering. Add
investment portfolio view with holdings table, allocation chart, and
gain/loss color coding. Includes TypeScript types and API services.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add API service files and replace stub views with full implementations:
- Budgets: month navigator, budget items table with progress bars, create/edit/delete
- Scheduled Transactions: data table with skip/post-now actions, add/edit dialog
- Loans: loan list, detail view with amortization schedule, payoff scenario calculator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete the import flow from file upload through duplicate resolution
to transaction creation. Previously, ResolveDuplicatesAsync was a stub
that only incremented counters, FileWatcherService detected files but
didn't process them, and ImportsView.vue ignored the API response.
Backend:
- Add ParsedDataJson column to ImportBatch to persist parsed data
between upload and confirm steps
- Rewrite ImportService.ResolveDuplicatesAsync to deserialize parsed
transactions and create/merge/skip based on user decisions, with
payee matching, fingerprinting, and account balance updates
- Add GetBatchesAsync for import history
- Complete FileWatcherService: wait for file ready, resolve account by
filename, call UploadAsync, send SignalR notification, archive file
- Add GET /api/imports/batches endpoint
Frontend:
- Create imports API service (frontend/src/services/imports.ts)
- Add ImportBatch, DuplicateResolution types
- Rewrite ImportsView.vue with 3-step Vuetify stepper wizard:
upload, review with duplicate handling, completion summary,
plus import history table
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The broad plugins/ and imports/ patterns were matching directories
at all levels, excluding frontend/src/plugins/vuetify.ts,
frontend/src/views/imports/, frontend/src/views/plugins/, and
src/Purrse.Tests/Plugins/. Changed to /plugins/ and /imports/
to only match root-level directories.
This was the root cause of the Docker build failure - vuetify.ts
was missing from the repo.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents node_modules/dist from polluting Docker build context.
Sets NODE_OPTIONS max-old-space-size=4096 for Vite builds on
memory-constrained servers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>