/** * Scope-parameterized authorization flow shared by MCP connections and * authored tools that declare `auth`. * * A *scope* is the stable identifier the per-step token cache and the * framework-owned callback URL are keyed by — a connection name for an * MCP connection, a tool name for tool-hosted auth. Everything else * (principal resolution, the park/resume webhook dance, the loop guard) * is identical across both, so it lives here once instead of being * duplicated per caller. */ import type { ConnectionAuthorizationChallenge } from "#public/connections/errors.js"; import { type AuthorizationSignal } from "#harness/authorization.js"; import { type AuthorizationDefinition, type ConnectionAuthorizationContext, type TokenResult } from "#runtime/connections/types.js"; /** * Everything the scoped authorization helpers need to drive one * authorization strategy: the cache/callback {@link scope}, the * authored {@link AuthorizationDefinition}, and the per-scope * {@link ConnectionAuthorizationContext} handed to every callback. */ export interface ScopedAuthorization { readonly scope: string; readonly authorization: Readonly; readonly connection: ConnectionAuthorizationContext; } /** * Resolves a bearer token for one scope, consulting the per-step token * cache before invoking the authored `getToken`. * * The cache is keyed by `(scope, principalKey(principal))` so concurrent * users on one session never alias onto each other's bearer. Outside a * runtime scope the cache is unavailable, but `getToken` still runs with * a framework-resolved principal so ad-hoc `"app"`-scoped use keeps * working; `"user"`-scoped strategies without a context fail fast inside * {@link resolveConnectionPrincipal}. * * `getToken` may throw {@link ConnectionAuthorizationRequiredError}; * callers catch it and drive {@link startScopedAuthorization}. */ export declare function resolveScopedToken(input: ScopedAuthorization): Promise; /** * Best-effort removal of a rejected bearer for one scope's resolved * principal, across every cache layer. * * Called when an already-resolved bearer is rejected (a downstream * `401`, or an explicit `requireAuth()` after a failed call) so the * re-authorization attempt does not re-read the stale token. Drops two * layers: eve's per-step cache, and — via the strategy's optional * {@link AuthorizationDefinition.evict} hook — any cache the strategy * itself owns (e.g. the `@vercel/connect` in-process token cache). The * single shared eviction path here means both authored tools and MCP * connections cascade identically. * * No-op outside a runtime scope or when the principal cannot be * resolved; a resolution failure here must never mask the underlying * authorization error that triggered the eviction. */ export declare function evictScopedToken(input: ScopedAuthorization): Promise; /** * Completes an authorization whose callback arrived this turn, caching * the freshly minted token under the scope. * * Returns `true` when a token was minted. Callers use the boolean as a * loop guard: a scope authorized this turn that still reports `Required` * on the immediately following call has a token the server itself * rejected, so it must fail terminally rather than re-challenge forever. * * No-op (returns `false`) when the strategy is not interactive or no * callback arrived for the scope. */ export declare function completeScopedAuthorization(input: ScopedAuthorization): Promise; /** * Starts an interactive authorization for one scope and returns the * {@link AuthorizationSignal} a tool returns to park the turn. * * Returns `undefined` when the strategy is not interactive or no * callback URL can be minted (for example outside a deployment), so * callers can fall through to rethrowing the original `Required` error. */ export declare function startScopedAuthorization(input: ScopedAuthorization): Promise; /** * Resolves the user-facing `displayName` onto a challenge before it is * surfaced on `authorization.required`. * * The agent author's static definition-level value wins over the * strategy-stamped one: an author writing * `auth: { ...connect("x"), displayName: "Y" }` is the most explicit * intent, while strategies provide defaults. Returns the input challenge * unchanged when the resolved value does not differ. */ export declare function stampChallengeDisplayName(challenge: ConnectionAuthorizationChallenge, authorization: Readonly): ConnectionAuthorizationChallenge;