feat(connections): Mercury bank feed — setup, callback, inbox posting - #364
Conversation
…rtner link The Mercury provider in the connections marketplace: a setup form (backfill start, treasury toggle, and — only where the deployment advertises it — a personal read-only token in place of OAuth), the `/connections/mercury-callback` redirect target, the provider label on the card, and the fiscal-calendar bootstrap state for a Mercury-only tenant. The QuickBooks-conflict and no-chart refusals from the backend are mapped to plain instructions. The Mercury partner page (`mercury.com/partner/robosystems`) is linked from the marketplace row and the form. Types follow `@robosystems/client` 1.17.0 (`provider: 'mercury'`, `mercury_config`); the bump lands with that release. Claude-Session: https://claude.ai/code/session_0188CbjDiNBtxdEYjSJ5Y7mX
A bank-feed line (Mercury) arrives captured with a suggested account and posts only once classified (robosystems #1382). The detail modal now shows a "Post to account" picker for bank_transaction / bank_fee / external_transfer events: the chart's active accounts minus the bank leg, preselected with the feed's suggestion and its source. Approve carries the choice into the commit as `metadata_patch.classified_element_id`; Classify records it without posting; an unclassified line cannot be approved from the UI. A split recorded over MCP is shown and posted as is. Preview reflects the chosen account. Other event types are untouched. Claude-Session: https://claude.ai/code/session_0188CbjDiNBtxdEYjSJ5Y7mX
…e classify transition `provider: 'mercury'`, `mercury_config`, and `transition_to: 'classified'` are generated-tier additions in 1.17.0; the setup form and the inbox picker on this branch type against them. Claude-Session: https://claude.ai/code/session_0188CbjDiNBtxdEYjSJ5Y7mX
|
Change classification: normal — platform or application code changed. A normal change carries a documented automated review on this pull request before merge, in place of a second human approver. The |
|
@claude please review this PR |
|
Claude finished @jfrench9's task in 2m 54s —— View job Reviewing PR #364
|
Review findings on #364: a classification seeded from the feed's suggestion or a prior choice could name an account that is no longer on the chart (retired since, or the bank leg itself). The select then showed "Choose an account…" while Approve would still post it. The seeded id is now checked against the loaded options and cleared when absent, so the refusal covers it. The Mercury callback page maps SDK errors through `friendlyError` instead of showing the raw envelope. Claude-Session: https://claude.ai/code/session_0188CbjDiNBtxdEYjSJ5Y7mX
|
Addressed:
|

Summary
The Mercury bank feed in the app: connect Mercury from the marketplace, and post the bank lines it captures from the inbox. Pairs with robosystems #1381 (the provider) and #1382 (the classify loop), both merged, over
@robosystems/client1.17.0. The provider is off in production until Mercury's compliance review clears the production client, so nothing new shows in the marketplace until the API flag is on.Changes
connections/content.tsx,components/MercurySetupForm.tsx): a Mercury setup form with the backfill start date, a treasury toggle, and — only where the API advertises it (optional_configcarriesapi_key, self-hosted deployments) — a personal read-only token in place of the OAuth sign-in. The two backend refusals are mapped to plain instructions: "sever QuickBooks first" and "initialize a chart of accounts first". The Mercury partner page (mercury.com/partner/robosystems, the referral link) is linked from the marketplace row and the form for anyone not yet banking there.connections/mercury-callback/page.tsx): the registered redirect target; mirrors the QuickBooks page without a realm, with a decline-at-Mercury path and a no-graph timeout.components/ConnectionCard.tsx): "Mercury" and "External" labels; the fiscal-calendar bootstrap state shows for Mercury as well as QuickBooks; the subtitle reads "Organization" for a bank feed.ledger/inbox/EventBlockDetailModal.tsx): a "Post to account" picker on bank-feed lines (bank_transaction,bank_fee,external_transfer): the chart's active accounts minus the bank leg, preselected with the feed's suggestion and its source. Approve carries the choice into the commit asmetadata_patch.classified_element_id; Classify records it without posting; an unclassified line cannot be approved from the UI (the API refuses it too). A split recorded over MCP is shown and posted as is. Preview reflects the chosen account. Other event types are unchanged — this is what a bookkeeper posts from a bank line, so the picker never touches the amount or the bank leg.@robosystems/client^1.17.0.Deploy Notes
mercuryprovider,mercury_config,transition_to: 'classified'). Against an older API the marketplace simply never lists Mercury and the picker never renders (bank-feed event types do not exist), so a mis-ordered deploy degrades to today's behavior rather than breaking.@robosystems/client1.16.0 → 1.17.0: additive types only; no existing call site changed shape.CONNECTION_MERCURY_ENABLED.Testing
npm run test:allgreen (format, lint, typecheck; 57 files, 423 tests).npm run buildgreen (new route).connections/__tests__/MercurySetupForm.test.tsx(create + OAuth redirect, api-key mode hidden on hosted, api-key connect skips OAuth, both refusal mappings, the partner link) andledger/inbox/__tests__/EventBlockDetailModal.test.tsx(tree flattening, bank-leg exclusion, suggestion preselect, approve carries the patch, unclassified refused, classify records without posting, MCP split shown as-is, non-bank events untouched).🤖 Generated with Claude Code
https://claude.ai/code/session_0188CbjDiNBtxdEYjSJ5Y7mX