Fix OAuth App picker showing apps from other integrations (part of #1120)#1139
Fix OAuth App picker showing apps from other integrations (part of #1120)#1139RhysSullivan wants to merge 1 commit into
Conversation
The "OAuth App" picker listed apps registered for other integrations (e.g. Datadog clients showing up under Atlassian). A discovery-only OAuth method declares no endpoints, so the picker hit its "no endpoints, show every app" branch and never consulted which integration an app was registered for. Record the integration each OAuth app was registered for (DCR and manual), threaded sdk -> api -> react via origin.integration, and match the picker by integration first, falling back to endpoint-domain matching only when endpoints are actually declared. Adds a selfhost e2e (oauth-picker-cross-integration) that registers a Datadog app, then opens the Atlassian picker and asserts the Atlassian app shows while the Datadog one does not.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-marketing | 4da05aa | Commit Preview URL Branch Preview URL |
Jun 26 2026, 05:40 AM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-cloud | 4da05aa | Jun 26 2026, 05:40 AM |
Cloudflare preview
Sign-in is Cloudflare Access (one-time PIN to an allowed email). The preview has its own database and encryption key; it is destroyed when this PR closes. |
@executor-js/cli
@executor-js/config
@executor-js/execution
@executor-js/sdk
@executor-js/codemode-core
@executor-js/runtime-quickjs
@executor-js/plugin-file-secrets
@executor-js/plugin-graphql
@executor-js/plugin-keychain
@executor-js/plugin-mcp
@executor-js/plugin-onepassword
@executor-js/plugin-openapi
executor
commit: |
Greptile SummaryThis PR fixes the OAuth app picker showing apps from unrelated integrations by recording
Confidence Score: 4/5Safe to merge — the fix is well-scoped, the logic change is guarded by a new selfhost e2e regression test, and all existing unit/typecheck suites pass. The core logic change in selectClientsForEndpoints is straightforward and correctly narrows the "show everything" early return to require both integration and endpoints to be absent. The UseOAuthClientsResult.endpointMatched field JSDoc is now partially stale — it describes only the endpoint-matching case but the field now also reflects integration-matching outcomes — leaving the interface docs misleading for future readers. No functional regressions are introduced. use-effective-oauth-client.tsx — the endpointMatched and displayRegisterCTA field docs should be updated to reflect the broadened semantics introduced by this change. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["selectClientsForEndpoints(all, {integration, tokenUrl, authorizationUrl})"] --> B{wantedIntegration\nAND/OR endpoints\npresent?}
B -- "neither present\n(no context at all)" --> C["Early return:\nall apps matched\n(legacy fall-through)"]
B -- "at least one signal" --> D["For each app:"]
D --> E{fitsIntegration?\norigin.integration\n=== wantedIntegration}
D --> F{fitsEndpoint?\ntokenRoot or\nauthRoot match}
E -- yes --> G["→ matched"]
F -- yes --> G
E -- no --> H{either fits?}
F -- no --> H
H -- no --> I["→ unmatched"]
G --> J{matched.length > 0?}
J -- yes --> K["endpointMatched=true\nclients=matched\notherClients=[]"]
J -- no --> L["endpointMatched=false\nclients=[]\notherClients=unmatched\ndisplayRegisterCTA=true"]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A["selectClientsForEndpoints(all, {integration, tokenUrl, authorizationUrl})"] --> B{wantedIntegration\nAND/OR endpoints\npresent?}
B -- "neither present\n(no context at all)" --> C["Early return:\nall apps matched\n(legacy fall-through)"]
B -- "at least one signal" --> D["For each app:"]
D --> E{fitsIntegration?\norigin.integration\n=== wantedIntegration}
D --> F{fitsEndpoint?\ntokenRoot or\nauthRoot match}
E -- yes --> G["→ matched"]
F -- yes --> G
E -- no --> H{either fits?}
F -- no --> H
H -- no --> I["→ unmatched"]
G --> J{matched.length > 0?}
J -- yes --> K["endpointMatched=true\nclients=matched\notherClients=[]"]
J -- no --> L["endpointMatched=false\nclients=[]\notherClients=unmatched\ndisplayRegisterCTA=true"]
|
Part of #1120 (1 of 4: foundational).
Problem
The "OAuth App" picker listed apps registered for other integrations, e.g. Datadog clients showing up under Atlassian. A discovery-only OAuth method declares no endpoints, so the picker fell into its "no endpoints, show every app" branch and never consulted which integration an app had been registered for.
Fix
Record the integration each OAuth app was registered for (both DCR and manual), threaded
sdk -> api -> reactasorigin.integration. The picker now matches by integration first, falling back to endpoint-domain matching only when endpoints are actually declared.Tests
Adds a selfhost e2e (
oauth-picker-cross-integration): registers a Datadog app, opens the Atlassian picker, and asserts the Atlassian app is shown while the Datadog one is not.Existing react unit + typecheck stay green (lint 0/0, typecheck 41/41, add-account-modal 21/21).
This is the base for the dedup-DCR PR, which stacks on this branch.