Skip to content

fix(integrations): resolve trading accounts from OAuth connections#124

Merged
TradingGoose-Dev merged 6 commits into
TradingGoose:stagingfrom
BWJ2310-backup:fix/integrations
May 24, 2026
Merged

fix(integrations): resolve trading accounts from OAuth connections#124
TradingGoose-Dev merged 6 commits into
TradingGoose:stagingfrom
BWJ2310-backup:fix/integrations

Conversation

@BWJ2310-backup
Copy link
Copy Markdown
Contributor

Summary

  • Reworked trading integrations to use user-owned OAuth connection accounts as the canonical broker access source.
  • Simplified portfolio identity discovery so routes, widgets, blocks, orders, holdings, and socket portfolio streams share the same connection-account contract.
  • Added explicit socket portfolio stream shutdown so broker polling stops during server termination.
  • Added a changelog entry and updated focused tests for the revised integration flow.

Why

Trading portfolio selection is based on connected broker OAuth accounts, but several paths still resolved those selections through workspace-scoped credential rows. That made account discovery and selected-account authorization drift across widgets, API routes, tools, and socket streams.

This change keeps broker account discovery tied to the signed-in user's connected OAuth accounts while preserving workspace checks around workspace-owned resources such as order history and order submission.

Affected Areas

  • apps/tradinggoose
  • apps/docs
  • packages/*
  • Workflows / execution
  • Realtime / sockets
  • Market data / charting
  • Dev tooling / CI / infra
  • Documentation only
  • Other: Trading integrations / OAuth connection account resolution

Issue Links( if any )

None.

Validation

cd apps/tradinggoose
bun run test lib/trading/portfolio-identities.test.ts app/api/providers/trading/portfolio-identities/route.test.ts app/api/providers/trading/order/route.test.ts 'app/api/orders/[orderId]/provider-detail/route.test.ts' socket-server/trading/portfolio-manager.test.ts tools/trading/holdings.test.ts widgets/widgets/components/trading-account-selector.test.tsx widgets/widgets/heatmap/components/body.test.tsx widgets/widgets/portfolio_snapshot/components/body.test.tsx widgets/widgets/quick_order/components/body.test.tsx
bun run type-check

Results:

  • Targeted test run passed: 10 test files, 90 tests.
  • Type-check passed: tsc --noEmit.

Risk / Rollout Notes

  • Behavior change: trading portfolio identity discovery no longer accepts workspaceId or workflowId; it now requires session auth and resolves the signed-in user's connected broker accounts.
  • Existing workspace checks remain around workspace resources such as order submission and recorded order detail.
  • Backout plan: revert this PR. No database or environment rollback is required.

Config / Data Changes

  • Env vars added or changed: None.
  • Database schema or migration impact: None.
  • External services or provider behavior changed: Broker account discovery now uses the user's OAuth connection accounts directly; provider API configuration is unchanged.

Screenshots / Video

Not applicable. No visible UI layout changes.

Checklist

  • I kept the change focused and reviewed my own diff
  • I validated the change locally and documented the results above
  • I updated docs, examples, or copy if behavior/user-facing flows changed
  • I called out any env, schema, provider, or rollout impact
  • I did not include secrets, tokens, or private credentials in this PR

BWJ2310 and others added 3 commits May 23, 2026 22:27
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
…h accounts and streamline portfolio identity discovery
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 24, 2026

Greptile Summary

This PR refactors broker account discovery across routes, widgets, tools, and socket streams to use the signed-in user's OAuth connection accounts directly, replacing the old workspace-scoped credential row path. It also wires in explicit socket portfolio stream shutdown and renames credentialIdtokenAccountId throughout the trading layer.

  • Core authorization rework: authorizeTradingCredentialRequest (workspace/workflow credential lookup) is replaced by authorizeTradingConnectionRequest (direct user OAuth account lookup); listOAuthCredentialAccountsForUser is removed in favor of listOAuthConnectionAccountsForUser, dropping the workspaceId requirement from portfolio identity discovery.
  • Socket shutdown: TradingPortfolioStreamManager.stop() is now called during server shutdown, clearing polling timers and a new stopped guard prevents re-arming during draining.
  • Historical order detail regression: Orders persisted before this PR stored credentialId in their request JSON; readOrderTokenAccountId reads the tokenAccountId key, so all such rows return null and getRecordedTradingOrderProviderDetail throws immediately, breaking provider-detail lookups for the existing order history.

Confidence Score: 4/5

Safe to merge for all new-order flows; existing order history provider-detail lookups will break for records created before this PR.

The authorization simplification and socket shutdown are clean and well-tested. The one concrete defect is in getRecordedTradingOrderProviderDetail: it now reads tokenAccountId from the stored request JSON, but every order written before this PR uses the old credentialId key. Those rows will hit the null-guard and throw, so any user who clicks provider detail on a historical order gets an error response.

apps/tradinggoose/lib/trading/order-detail.ts — the tokenAccountId read has no fallback for pre-migration rows

Important Files Changed

Filename Overview
apps/tradinggoose/lib/trading/order-detail.ts Removed credentialId path, added tokenAccountId lookup — historical order records without tokenAccountId in request JSON will fail provider-detail retrieval
apps/tradinggoose/lib/trading/context.ts Replaced credential-based authorization with direct OAuth connection account lookup; simplified PreflightContext by removing credentialId field
apps/tradinggoose/lib/credentials/oauth.ts Split listOAuthConnectionsForUser; added listOAuthConnectionAccountsForUser and resolveOAuthConnectionAccountForUser; removed workspace-scoped listOAuthCredentialAccountsForUser
apps/tradinggoose/lib/trading/portfolio-identities.ts Dropped workspaceId param; now resolves portfolio identities directly from user OAuth connection accounts
apps/tradinggoose/socket-server/trading/portfolio-manager.ts Added stopped guard, stop() shutdown method, pollState early-exit on stopped, and switched from credential to connection account resolution
apps/tradinggoose/socket-server/index.ts Added explicit tradingPortfolioStreamManager.stop() during shutdown and switched httpServer.close to io.close for proper Socket.IO drain
apps/tradinggoose/lib/trading/orders.ts Dropped request/workspaceId/workflowId params; stores tokenAccountId instead of credentialId in order history request JSON going forward
apps/tradinggoose/app/api/providers/trading/portfolio-identities/route.ts Removed workspaceId/workflowId query params and workspace/workflow access guards; authentication check retained
apps/tradinggoose/providers/trading/portfolio-identity.ts Renamed credentialId → tokenAccountId throughout PortfolioIdentity type, value object parser, and identity key builder
apps/tradinggoose/widgets/widgets/components/trading-services.ts Switched from workspace-scoped credential query to user-scoped OAuth connections query; dropped workspaceId param

Fix All in Codex Fix All in Claude Code Fix All in Cursor

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/tradinggoose/lib/trading/order-detail.ts:64-68
**Historical order records will fail provider-detail lookup**

`readOrderTokenAccountId` reads the `tokenAccountId` key from the stored `order.request` JSON, but orders submitted before this PR were persisted with the key `credentialId` (written by the old `orders.ts` path). For any such row, `readOrderTokenAccountId` returns `null` and the guard on line 66 throws `'Order history record is missing trading connection context'`, making every historical order's provider-detail endpoint return a 400/500. A fallback read (`readOrderRequestString(row, 'credentialId')`) would at least let old records surface a useful error, or the guard could skip the provider-lookup path gracefully for legacy rows.

Reviews (3): Last reviewed commit: "perf(trading): defer oauth connections q..." | Re-trigger Greptile

Comment thread apps/tradinggoose/socket-server/trading/portfolio-manager.ts
@TradingGoose-Dev
Copy link
Copy Markdown
Contributor

@greptileai

BWJ2310 and others added 2 commits May 24, 2026 14:07
@TradingGoose-Dev
Copy link
Copy Markdown
Contributor

@greptileai

Comment on lines +64 to 68
const tokenAccountId = readOrderTokenAccountId(order)
const serviceId = readOrderServiceId(order)
if (!credentialId || !serviceId) {
throw new TradingServiceError('Order history record is missing trading credential context')
if (!tokenAccountId || !serviceId) {
throw new TradingServiceError('Order history record is missing trading connection context')
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Historical order records will fail provider-detail lookup

readOrderTokenAccountId reads the tokenAccountId key from the stored order.request JSON, but orders submitted before this PR were persisted with the key credentialId (written by the old orders.ts path). For any such row, readOrderTokenAccountId returns null and the guard on line 66 throws 'Order history record is missing trading connection context', making every historical order's provider-detail endpoint return a 400/500. A fallback read (readOrderRequestString(row, 'credentialId')) would at least let old records surface a useful error, or the guard could skip the provider-lookup path gracefully for legacy rows.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/tradinggoose/lib/trading/order-detail.ts
Line: 64-68

Comment:
**Historical order records will fail provider-detail lookup**

`readOrderTokenAccountId` reads the `tokenAccountId` key from the stored `order.request` JSON, but orders submitted before this PR were persisted with the key `credentialId` (written by the old `orders.ts` path). For any such row, `readOrderTokenAccountId` returns `null` and the guard on line 66 throws `'Order history record is missing trading connection context'`, making every historical order's provider-detail endpoint return a 400/500. A fallback read (`readOrderRequestString(row, 'credentialId')`) would at least let old records surface a useful error, or the guard could skip the provider-lookup path gracefully for legacy rows.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Codex Fix in Claude Code Fix in Cursor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@greptileai

The report is real only for old local/dev rows. It is not a current canonical-flow bug.

Current code is consistent:

I would not add a credentialId fallback. That is legacy compatibility and violates AGENTS.md.

Concise resolution: clear or normalize old dev orderHistoryTable rows. If the old request.credentialId value is actually an OAuth account.id, this one-time data cleanup works:

UPDATE "orderHistoryTable"
SET request = (request - 'credentialId')
  || jsonb_build_object('tokenAccountId', request->>'credentialId')
WHERE request ? 'credentialId'
  AND NOT request ? 'tokenAccountId';

If old credentialId values are workspace credential IDs, there is no canonical runtime fallback. Delete/recreate those dev orders or do a one-time manual data repair by joining through the credential table outside app code.

Validation passed:

45 tests passed:
app/api/orders/[orderId]/provider-detail/route.test.ts
app/api/providers/trading/order/route.test.ts
lib/trading/order-records.test.ts

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point — AGENTS.md is explicit: "no legacy backfill path," full stop. The suggestion to add a credentialId fallback read conflicts directly with that constraint, and I should have flagged that tension rather than recommending it.

Your analysis is correct:

  • The write/read/authorize chain is internally consistent on tokenAccountId post-PR
  • Any breakage is isolated to pre-PR local dev rows, not canonical production data
  • The SQL repair script you provided is the right remediation path (assuming old credentialId values are OAuth account.ids; manual repair otherwise)

The original comment is resolved. No code change needed here.

Tip: You can give me more context with .greptile/rules.md so I get this right next time.

@TradingGoose-Dev TradingGoose-Dev merged commit 08767b1 into TradingGoose:staging May 24, 2026
@BWJ2310-backup BWJ2310-backup deleted the fix/integrations branch May 24, 2026 20:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants