/** * Deciding how to connect Google, before doing anything about it. * * The defect this exists to fix: a machine that already held a working OAuth * client id and client secret was walked through the new-project Branding * workflow anyway, because the only OAuth path began at "install gcloud" and * marched through project creation, API enablement, consent-screen branding * and audience publishing before it ever reached the one step that was * actually outstanding. Twenty minutes of a person's evening went into * re-deciding facts the machine already knew. * * So nothing runs until this module has looked at what is already true. The * succession is fixed and it is short: * * (a) A complete credential in the encrypted store, client, secret and * refresh token. Use it. Refresh it. Zero user actions. * (b) A client id and secret in the store with no refresh token. The only * thing missing is a person's consent, so go STRAIGHT to a consent URL. * Never to a project, a branding page or an audience setting, those * already exist or the client could not. * (c) An authenticated gcloud CLI. It names the Google account, finds the * project and enables the APIs with no clicking (see gcloud-posture.ts). * (d) Only then the guided path that creates a client from nothing. * * ── What is deliberately NOT here ───────────────────────────────────────── * * There is no filesystem scan. An earlier design probed `~/.gmail-mcp` on * every status call and offered to adopt whatever it found, and that is not * how this should behave: ordinary people do not have that directory, a * connector that goes looking through home directories for credential files * is doing something nobody asked it to, and an unprompted "I found some * credentials, shall I use them?" is a question rather than a connection. * * Credentials on disk are still fully supported, they are just USER-DIRECTED * rather than discovered. When someone names a path, adoption runs exactly as * it always did and says what it took up and where it now lives. That route * lives in setup-actions.ts, reached from an explicit command, and it is * never entered from here. */ import { type GcloudPosture } from './gcloud-posture.js'; import type { GoogleCommandPort, GoogleConfigPort, GoogleSecretPort, GoogleSetupPath } from './types.js'; /** Which route the flow should take. Ordered exactly as the succession above. */ export type GoogleConnectionRoute = /** (a) A complete credential is stored. Nothing to ask anyone. */ 'stored-credential' /** (b) A client exists; only consent is missing. Straight to the URL. */ | 'stored-client-consent' /** (c) gcloud is signed in and can carry the project and API work. */ | 'gcloud-assisted' /** (d) Nothing exists yet; the client has to be created in the console. */ | 'guided-new-client'; export interface GoogleConnectionPlan { readonly route: GoogleConnectionRoute; /** * How many things the person has to do, counted honestly. * * The bar for this product is at most ONE, click a consent link and * approve. Any route that reports more carries its reason in `whyExtraSteps` * and that reason has to be a fact about Google, not a convenience for us. */ readonly userActionsRequired: number; /** Present only when `userActionsRequired` exceeds one. */ readonly whyExtraSteps: string | null; /** The setup path to run, when a flow run is what comes next. */ readonly setupPath: GoogleSetupPath | null; /** * The Google account this connection is meant to be for, when anything * knows it. Becomes the consent screen's `login_hint`, which is what keeps * a person from approving as their personal account by reflex. */ readonly intendedAccount: string | null; /** What gcloud said, when it was consulted. Null on routes (a) and (b). */ readonly gcloud: GcloudPosture | null; /** Plain-language statement of what was found and what happens next. */ readonly detail: string; } export interface GoogleDiscoverySources { readonly config: GoogleConfigPort; readonly secrets: GoogleSecretPort; /** Consulted only when the store has nothing usable. */ readonly commands: GoogleCommandPort; readonly homeDirectory: string; } /** * Work out how to connect, without changing anything. * * Pure inspection: this reads config and probes for the presence of secrets, * and it runs gcloud only when the store cannot answer. It never writes, never * opens a browser and never asks anyone anything. */ export declare function planGoogleConnection(sources: GoogleDiscoverySources): Promise; /** * The plan as lines for a transcript or a status panel. * * Leads with what happens next rather than with an inventory, because the * question a person asked was "connect google", not "audit my machine". */ export declare function describeGoogleConnectionPlan(plan: GoogleConnectionPlan): readonly string[]; //# sourceMappingURL=discovery.d.ts.map