@@ -42,19 +42,14 @@ import {
4242 PluginsProvider ,
4343 collectTables ,
4444} from "@executor-js/api/server" ;
45- import { googleCatalogOAuthScopesForPreset } from "@executor-js/plugin-openapi/providers/google" ;
46- import { slackMcpUserScopes } from "@executor-js/react/lib/slack-mcp-oauth" ;
4745import { makeDynamicWorkerExecutor } from "@executor-js/runtime-dynamic-worker" ;
48- import {
49- IntegrationSlug ,
50- type AnyPlugin ,
51- type FirstPartyOAuthClientConfig ,
52- } from "@executor-js/sdk" ;
46+ import { type AnyPlugin } from "@executor-js/sdk" ;
5347
5448import executorConfig from "../../executor.config" ;
5549import { cloudEnterpriseManagedRollout } from "../analytics/ema-rollout" ;
5650import { DbService } from "../db/db" ;
5751import { cloudDbProviderLayer } from "../db/fuma" ;
52+ import { firstPartyOAuthClientsFor } from "./first-party-oauth-clients" ;
5853
5954export { makeExecutionStack } from "@executor-js/api/server" ;
6055
@@ -95,98 +90,6 @@ export const CloudPluginsProvider: Layer.Layer<PluginsProvider> = Layer.succeed(
9590 */
9691export const CLOUD_MOUNT_PREFIX = "/api" as const ;
9792
98- // Consumer Google launch boundary. Keep this list aligned with the scopes
99- // submitted for the Executor-owned production app: ordinary Workspace services
100- // plus Photos, Meet, and Search Console. Admin, Classroom, YouTube, Apps Script,
101- // BigQuery, and Cloud Resource Manager have materially different audiences or
102- // provider requirements and remain BYO OAuth. The same scope source builds each
103- // catalog auth template, preventing picker/start drift.
104- const GOOGLE_FIRST_PARTY_PRESET_IDS = [
105- "google-calendar" ,
106- "google-meet" ,
107- "google-gmail" ,
108- "google-sheets" ,
109- "google-drive" ,
110- "google-docs" ,
111- "google-slides" ,
112- "google-forms" ,
113- "google-tasks" ,
114- "google-people" ,
115- "google-photos-library" ,
116- "google-photos-picker" ,
117- "google-search-console" ,
118- ] as const ;
119-
120- const GOOGLE_FIRST_PARTY_ALLOWED_SCOPES : readonly string [ ] = [
121- ...new Set ( [
122- ...GOOGLE_FIRST_PARTY_PRESET_IDS . flatMap ( googleCatalogOAuthScopesForPreset ) ,
123- // Connections created before the full-Gmail review retain this declared
124- // scope on reconnect. New Gmail presets request `mail.google.com`.
125- "https://www.googleapis.com/auth/gmail.modify" ,
126- ] ) ,
127- ] ;
128-
129- // Executor-owned provider apps, enabled per provider by setting BOTH env vars
130- // (id + secret). Each provider-side registration must list
131- // `${VITE_PUBLIC_SITE_URL}/api/oauth/callback` as its callback; the org slug
132- // travels inside OAuth `state`, so the single static callback serves every org.
133- //
134- // The endpoint URLs default to the real provider; the `_AUTHORIZE_URL` /
135- // `_TOKEN_URL` overrides exist so tests and dev instances can point the app at
136- // an emulated provider (`@executor-js/emulate`) and run the complete flow.
137- // Production leaves them unset.
138- export const cloudFirstPartyOAuthClients = ( ) : readonly FirstPartyOAuthClientConfig [ ] => [
139- ...( env . FIRST_PARTY_GITHUB_CLIENT_ID && env . FIRST_PARTY_GITHUB_CLIENT_SECRET
140- ? [
141- {
142- name : "github" ,
143- authorizationUrl :
144- env . FIRST_PARTY_GITHUB_AUTHORIZE_URL ?? "https://github.com/login/oauth/authorize" ,
145- tokenUrl :
146- env . FIRST_PARTY_GITHUB_TOKEN_URL ?? "https://github.com/login/oauth/access_token" ,
147- clientId : env . FIRST_PARTY_GITHUB_CLIENT_ID ,
148- clientSecret : env . FIRST_PARTY_GITHUB_CLIENT_SECRET ,
149- integrations : [ IntegrationSlug . make ( "github_rest" ) ] ,
150- // GitHub App user access tokens do not use classic OAuth scopes;
151- // their capabilities come from the app's registered permissions.
152- authorizationScopes : [ ] ,
153- } ,
154- ]
155- : [ ] ) ,
156- ...( env . FIRST_PARTY_GOOGLE_CLIENT_ID && env . FIRST_PARTY_GOOGLE_CLIENT_SECRET
157- ? [
158- {
159- name : "google" ,
160- authorizationUrl : "https://accounts.google.com/o/oauth2/v2/auth" ,
161- tokenUrl : "https://oauth2.googleapis.com/token" ,
162- clientId : env . FIRST_PARTY_GOOGLE_CLIENT_ID ,
163- clientSecret : env . FIRST_PARTY_GOOGLE_CLIENT_SECRET ,
164- allowedScopes : GOOGLE_FIRST_PARTY_ALLOWED_SCOPES ,
165- // Withdrawn from the connect picker: no new connection is offered the
166- // Executor-owned Google app. The entry stays declared on purpose —
167- // every connection already minted against it keeps refreshing and
168- // reconnecting through it. Deleting this block, or unsetting the env
169- // vars, would strand those connections instead.
170- unlisted : true ,
171- } ,
172- ]
173- : [ ] ) ,
174- ...( env . FIRST_PARTY_SLACK_CLIENT_ID && env . FIRST_PARTY_SLACK_CLIENT_SECRET
175- ? [
176- {
177- name : "slack" ,
178- authorizationUrl : "https://slack.com/oauth/v2_user/authorize" ,
179- tokenUrl : "https://slack.com/api/oauth.v2.user.access" ,
180- resource : "https://mcp.slack.com" ,
181- clientId : env . FIRST_PARTY_SLACK_CLIENT_ID ,
182- clientSecret : env . FIRST_PARTY_SLACK_CLIENT_SECRET ,
183- integrations : [ IntegrationSlug . make ( "slack" ) ] ,
184- allowedScopes : slackMcpUserScopes ,
185- } ,
186- ]
187- : [ ] ) ,
188- ] ;
189-
19093export const CloudHostConfig : Layer . Layer < HostConfig > = Layer . sync ( HostConfig , ( ) => ( {
19194 // SSRF / private-network egress guard. Config-driven, NOT a test flag:
19295 // production leaves `ALLOW_LOCAL_NETWORK` unset so the guard stays ON (`false`);
@@ -198,7 +101,7 @@ export const CloudHostConfig: Layer.Layer<HostConfig> = Layer.sync(HostConfig, (
198101 // WorkOS Vault is cloud's credential storage implementation detail, not a
199102 // user-selectable provider surface.
200103 exposeCredentialProviders : false ,
201- firstPartyOAuthClients : cloudFirstPartyOAuthClients ( ) ,
104+ firstPartyOAuthClients : firstPartyOAuthClientsFor ( env ) ,
202105 // Workers cancel request-scoped I/O once the response settles; the ambient
203106 // `waitUntil` binds to the in-flight invocation (HTTP request or DO call),
204107 // so stale tool-catalog rebuilds that outlive a read still converge.
0 commit comments