MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / start

Function start

packages/core/sdk/src/oauth-service.ts:1044–1247  ·  view source on GitHub ↗
(
    input: OAuthStartInput,
  )

Source from the content-addressed store, hash-verified

1042 // start — begin a flow through a client to mint a connection.
1043 // -----------------------------------------------------------------------
1044 const start = (
1045 input: OAuthStartInput,
1046 ): Effect.Effect<ConnectResult, OAuthStartError | StorageFailure> =>
1047 Effect.gen(function* () {
1048 const keys = yield* Effect.try({
1049 try: () => deps.ownedKeys(input.owner),
1050 catch: (cause) =>
1051 new StorageError({
1052 message: "Cannot start OAuth flow for owner without a subject",
1053 cause,
1054 }),
1055 });
1056 // Sharing is one-directional (org → members): a Workspace (org) connection
1057 // cannot be backed by a member's private (user) app. The connection owner
1058 // and the app owner are otherwise independent — a Personal connection
1059 // through a shared Workspace app is the supported cross-owner case.
1060 if (input.owner === "org" && input.clientOwner === "user") {
1061 return yield* new OAuthStartError({
1062 message: "A Workspace connection must use a Workspace app.",
1063 });
1064 }
1065 // Load the app by its EXPLICIT owner (the caller knows it — no derivation).
1066 // The connection is still minted under `input.owner`. Storage visibility
1067 // policy hides apps the actor cannot see, so a wrong owner yields null.
1068 const client = yield* loadClient(input.clientOwner, input.client);
1069 if (!client) {
1070 return yield* new OAuthStartError({
1071 message: `OAuth client not found: ${input.client}`,
1072 });
1073 }
1074
1075 // newConnection: resolve the requested name to a FREE one against the
1076 // stored rows (not a client-side, policy-filtered view), so a second
1077 // untyped connect mints `personalGmail2` instead of silently re-minting
1078 // the first account's row. Reconnects omit the flag and keep targeting
1079 // their existing row. Bounded: a pathological owner with 1000 same-named
1080 // connections fails loudly rather than scanning forever.
1081 let name = input.name;
1082 if (input.newConnection === true) {
1083 let suffix = 2;
1084 while (
1085 yield* deps.connectionNameTaken({
1086 owner: input.owner,
1087 integration: input.integration,
1088 name,
1089 })
1090 ) {
1091 if (suffix > 1000) {
1092 return yield* new OAuthStartError({
1093 message: `No free connection name derivable from ${input.name}.`,
1094 });
1095 }
1096 name = ConnectionName.make(`${String(input.name)}${suffix}`);
1097 suffix++;
1098 }
1099 }
1100
1101 // Declared scopes win (driven by the selected auth template). MCP-style

Callers

nothing calls this directly

Calls 13

createPkceCodeVerifierFunction · 0.90
createPkceCodeChallengeFunction · 0.90
createOAuthStateFunction · 0.90
encodeOAuthCallbackStateFunction · 0.90
buildAuthorizationUrlFunction · 0.90
providerAuthorizeExtrasFunction · 0.90
loadClientFunction · 0.85
dedupeScopesFunction · 0.85
mintFromTokenFunction · 0.85

Tested by

no test coverage detected