/** * Internal routes for daemon-owned OAuth connect flows (CLI gateway transport fix). * * POST internal/oauth/connect/start — starts the flow in the daemon, returns auth URL * GET internal/oauth/connect/status/:state — polls current flow status */ import { z } from "zod"; import { orchestrateOAuthConnect } from "../../oauth/connect-orchestrator.js"; import { getOAuthConnectState, setOAuthConnectComplete, setOAuthConnectError, setOAuthConnectPending, } from "../../oauth/oauth-connect-state.js"; import { getAppByProviderAndClientId, getAppClientSecret, getMostRecentAppByProvider, getProvider, } from "../../oauth/oauth-store.js"; import { getLogger } from "../../util/logger.js"; import { GATEWAY_PRINCIPALS } from "../auth/route-policy.js"; import { BadRequestError, InternalError, NotFoundError } from "./errors.js"; import type { RouteDefinition } from "./types.js"; const log = getLogger("oauth-connect-routes"); async function handleOAuthConnectStart({ body, }: { body?: Record; }): Promise<{ auth_url: string; state: string }> { const { service, clientId: rawClientId, clientSecret: rawClientSecret, callbackTransport, requestedScopes, } = (body ?? {}) as { service: string; clientId?: string; clientSecret?: string; callbackTransport?: string; requestedScopes?: string[]; }; if (!service) { throw new BadRequestError("service is required"); } // Provider row drives validation that applies regardless of whether the // caller supplied an explicit clientId: existence, manual-token rejection, // and the requiresClientSecret check below. const providerRow = getProvider(service); if (!providerRow) { throw new NotFoundError( `Unknown provider "${service}". Run 'assistant oauth providers list' to see available providers.`, ); } // Manual-token providers don't use OAuth2 browser flows. if (providerRow.authorizeUrl === "urn:manual-token") { throw new BadRequestError( `"${service}" uses manual token configuration, not an OAuth browser flow. ` + `Collect the token securely with: assistant credentials prompt --service ${service} --field --label "