@@ -42,18 +42,13 @@ 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 { DbService } from "../db/db" ;
5650import { cloudDbProviderLayer } from "../db/fuma" ;
51+ import { firstPartyOAuthClientsFor } from "./first-party-oauth-clients" ;
5752
5853export { makeExecutionStack } from "@executor-js/api/server" ;
5954
@@ -94,92 +89,6 @@ export const CloudPluginsProvider: Layer.Layer<PluginsProvider> = Layer.succeed(
9489 */
9590export const CLOUD_MOUNT_PREFIX = "/api" as const ;
9691
97- // Consumer Google launch boundary. Keep this list aligned with the scopes
98- // submitted for the Executor-owned production app: ordinary Workspace services
99- // plus Photos, Meet, and Search Console. Admin, Classroom, YouTube, Apps Script,
100- // BigQuery, and Cloud Resource Manager have materially different audiences or
101- // provider requirements and remain BYO OAuth. The same scope source builds each
102- // catalog auth template, preventing picker/start drift.
103- const GOOGLE_FIRST_PARTY_PRESET_IDS = [
104- "google-calendar" ,
105- "google-meet" ,
106- "google-gmail" ,
107- "google-sheets" ,
108- "google-drive" ,
109- "google-docs" ,
110- "google-slides" ,
111- "google-forms" ,
112- "google-tasks" ,
113- "google-people" ,
114- "google-photos-library" ,
115- "google-photos-picker" ,
116- "google-search-console" ,
117- ] as const ;
118-
119- const GOOGLE_FIRST_PARTY_ALLOWED_SCOPES : readonly string [ ] = [
120- ...new Set ( [
121- ...GOOGLE_FIRST_PARTY_PRESET_IDS . flatMap ( googleCatalogOAuthScopesForPreset ) ,
122- // Connections created before the full-Gmail review retain this declared
123- // scope on reconnect. New Gmail presets request `mail.google.com`.
124- "https://www.googleapis.com/auth/gmail.modify" ,
125- ] ) ,
126- ] ;
127-
128- // Executor-owned provider apps, enabled per provider by setting BOTH env vars
129- // (id + secret). Each provider-side registration must list
130- // `${VITE_PUBLIC_SITE_URL}/api/oauth/callback` as its callback; the org slug
131- // travels inside OAuth `state`, so the single static callback serves every org.
132- //
133- // The endpoint URLs default to the real provider; the `_AUTHORIZE_URL` /
134- // `_TOKEN_URL` overrides exist so tests and dev instances can point the app at
135- // an emulated provider (`@executor-js/emulate`) and run the complete flow.
136- // Production leaves them unset.
137- const cloudFirstPartyOAuthClients = ( ) : readonly FirstPartyOAuthClientConfig [ ] => [
138- ...( env . FIRST_PARTY_GITHUB_CLIENT_ID && env . FIRST_PARTY_GITHUB_CLIENT_SECRET
139- ? [
140- {
141- name : "github" ,
142- authorizationUrl :
143- env . FIRST_PARTY_GITHUB_AUTHORIZE_URL ?? "https://github.com/login/oauth/authorize" ,
144- tokenUrl :
145- env . FIRST_PARTY_GITHUB_TOKEN_URL ?? "https://github.com/login/oauth/access_token" ,
146- clientId : env . FIRST_PARTY_GITHUB_CLIENT_ID ,
147- clientSecret : env . FIRST_PARTY_GITHUB_CLIENT_SECRET ,
148- integrations : [ IntegrationSlug . make ( "github_rest" ) ] ,
149- // GitHub App user access tokens do not use classic OAuth scopes;
150- // their capabilities come from the app's registered permissions.
151- authorizationScopes : [ ] ,
152- } ,
153- ]
154- : [ ] ) ,
155- ...( env . FIRST_PARTY_GOOGLE_CLIENT_ID && env . FIRST_PARTY_GOOGLE_CLIENT_SECRET
156- ? [
157- {
158- name : "google" ,
159- authorizationUrl : "https://accounts.google.com/o/oauth2/v2/auth" ,
160- tokenUrl : "https://oauth2.googleapis.com/token" ,
161- clientId : env . FIRST_PARTY_GOOGLE_CLIENT_ID ,
162- clientSecret : env . FIRST_PARTY_GOOGLE_CLIENT_SECRET ,
163- allowedScopes : GOOGLE_FIRST_PARTY_ALLOWED_SCOPES ,
164- } ,
165- ]
166- : [ ] ) ,
167- ...( env . FIRST_PARTY_SLACK_CLIENT_ID && env . FIRST_PARTY_SLACK_CLIENT_SECRET
168- ? [
169- {
170- name : "slack" ,
171- authorizationUrl : "https://slack.com/oauth/v2_user/authorize" ,
172- tokenUrl : "https://slack.com/api/oauth.v2.user.access" ,
173- resource : "https://mcp.slack.com" ,
174- clientId : env . FIRST_PARTY_SLACK_CLIENT_ID ,
175- clientSecret : env . FIRST_PARTY_SLACK_CLIENT_SECRET ,
176- integrations : [ IntegrationSlug . make ( "slack" ) ] ,
177- allowedScopes : slackMcpUserScopes ,
178- } ,
179- ]
180- : [ ] ) ,
181- ] ;
182-
18392export const CloudHostConfig : Layer . Layer < HostConfig > = Layer . sync ( HostConfig , ( ) => ( {
18493 // SSRF / private-network egress guard. Config-driven, NOT a test flag:
18594 // production leaves `ALLOW_LOCAL_NETWORK` unset so the guard stays ON (`false`);
@@ -191,7 +100,7 @@ export const CloudHostConfig: Layer.Layer<HostConfig> = Layer.sync(HostConfig, (
191100 // WorkOS Vault is cloud's credential storage implementation detail, not a
192101 // user-selectable provider surface.
193102 exposeCredentialProviders : false ,
194- firstPartyOAuthClients : cloudFirstPartyOAuthClients ( ) ,
103+ firstPartyOAuthClients : firstPartyOAuthClientsFor ( env ) ,
195104} ) ) ;
196105
197106export const CloudCodeExecutorProvider : Layer . Layer < CodeExecutorProvider > = Layer . sync (
0 commit comments