Riddy21 / Riddy21/Friday_Budgeting_Pro
[Bug] refresh_connection does not use Plaid Update Mode — re-auth creates new connection instead of updating existing
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
What was broken
Root Cause 1: No true Plaid Update Mode
refresh_connection generated a generic new Link token by calling create_link_token() with no access_token parameter. This is identical to starting a fresh bank link — Plaid has no way to know which existing connection to re-authenticate, so the user would end up with a duplicate connection and the stale one would remain needs_reauth.
Related: issue #34 (TODO was tracked there but never resolved).
Root Cause 2: disconnect FK constraint failure
When a connection has linked bank_accounts and associated transactions / transaction_entries, deleting the bank_connections row raised a FOREIGN KEY constraint failed error because child rows were not cleaned up first. This made it impossible to remove a real connection via the MCP tool or UI without manual DB surgery.
Root Cause 3: No graceful re-auth path
There was no end-to-end flow for re-authenticating a needs_reauth connection while preserving history. The only option was disconnect (broken) + reconnect (creates duplicate).
What was fixed
Fix 1: True Plaid Update Mode in PlaidProvider.create_link_token
Added an optional access_token parameter to PlaidProvider.create_link_token(). When provided, the link token request omits products and passes access_token — this is the documented Plaid Update Mode pattern that lets a user re-authenticate an existing item in-place.
Fix 2: refresh_connection now fetches and decrypts the stored token
refresh_connection(id) now:
- Looks up the connection row in the DB
- Decrypts the stored
plaid_access_token_encrypted - Calls
provider.create_link_token(access_token=<decrypted>)for true Update Mode - Embeds
connection_idin the returned URL so/link/completeknows to update the existing row
Fix 3: complete_link Update Mode
Added optional connection_id parameter to complete_link(). When present:
- Exchanges the public token (Plaid returns the same access token after re-auth)
- Updates the existing
bank_connectionsrow (status='active', refreshed token) - Does not insert a duplicate row
Fix 4: Cascade delete in disconnect
disconnect() now deletes child rows in FK order before removing the connection:
transaction_entries → transactions → bank_accounts → sync_cursors → bank_connections
All wrapped in a single transaction for atomicity.
Fix 5: UI flow end-to-end
/linkroute now accepts optionalconnection_idquery paramlink.htmlinjectsconnection_idas a hidden form field when present/link/completereadsconnection_idfrom the POST body and passes it tocomplete_link()
Files changed
server/providers/plaid.py— Update Mode support increate_link_tokenserver/main.py—refresh_connection,complete_link,disconnectui/server.py—/linkroute and/link/completeendpointui/templates/link.html— hiddenconnection_idfieldtests/test_bank_tools.py— new tests for Update Mode, cascade delete, and unknown-id error
All existing tests pass (pre-existing unrelated failure in test_ledger_mcp_tools.py unchanged).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading server/providers/plaid.py and the refresh_connection, complete_link, and disconnect paths in server/main.py. Then inspect ui/server.py, ui/templates/link.html, and tests/test_bank_tools.py to understand the end-to-end flow. Done means Update Mode preserves the existing connection, disconnect removes dependent rows atomically, and the named tests pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, database, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100