/**
 * OAuth 2.0 Authorization Server routes
 *
 * Makes Studiograph's `/mcp` server connectable by Claude Desktop's Chat/Cowork
 * connector pipeline (OAuth-only). Implements the minimal authorization-server
 * surface an MCP client drives:
 *
 *   GET  /.well-known/oauth-protected-resource[/mcp]  — resource metadata
 *   GET  /.well-known/oauth-authorization-server      — AS metadata
 *   POST /oauth/register                              — Dynamic Client Registration
 *   GET  /oauth/authorize                             — consent screen
 *   POST /oauth/authorize                             — consent submit → code
 *   POST /oauth/token                                 — code + refresh grants
 *   POST /oauth/revoke                                — revoke a refresh token
 *
 * Security posture (see plan reflective-sprouting-turtle):
 *   - Issuer + endpoint URLs are PINNED to a configured canonical base URL,
 *     never the inbound Host header (metadata-spoofing defense).
 *   - DCR is unauthenticated (the client has no user yet) but rate-limited,
 *     and redirect URIs are validated (https-only, no fragments/wildcards).
 *   - PKCE S256 is mandatory; authorization codes are single-use, ≤60s.
 *   - The consent form carries an HMAC-signed blob of the authorize params
 *     (incl. `state` + the logged-in userId) so the POST can't be forged.
 *   - All values rendered into the consent HTML are escaped (DCR is attacker-
 *     controlled). Token responses are `Cache-Control: no-store`.
 *   - Access tokens are minted with `aud = <canonical>/mcp`; the global auth
 *     hook scopes them to `/mcp` + `/oauth/*`.
 */
import type { FastifyInstance, FastifyRequest } from 'fastify';
import type { AuthService } from '../../services/auth-service.js';
interface WorkspaceConfigLike {
    server_url?: unknown;
    [k: string]: unknown;
}
/** Thrown when no canonical URL is pinned in a proxied/production-like deployment. */
export declare class CanonicalUrlError extends Error {
    constructor();
}
/**
 * Resolve the canonical public base URL for this tenant, in priority order:
 *   1. STUDIOGRAPH_PUBLIC_URL env (explicit operator override)
 *   2. workspace config `server_url`
 *   3. RAILWAY_PUBLIC_DOMAIN env → https://<domain>
 *   4. request origin (LOCAL DEV ONLY fallback)
 * Trailing slash stripped. Pinning to a configured value (not the inbound
 * Host header) is what prevents discovery-metadata spoofing behind a proxy.
 *
 * **Fails closed:** in a proxied/production-like deployment (`mustPinIssuer`)
 * with no pinned value, throws `CanonicalUrlError` rather than trusting the
 * (spoofable) forwarded Host. The dev fallback to request origin only applies
 * locally, where there is no untrusted proxy in front.
 */
export declare function resolveCanonicalBaseUrl(workspaceConfig: WorkspaceConfigLike, req: FastifyRequest): string;
/** True if a stable canonical URL is configured (not relying on the dev fallback). */
export declare function hasCanonicalUrl(workspaceConfig: WorkspaceConfigLike): boolean;
/**
 * Same-origin guard for post-login `returnTo` paths. Returns the path only if
 * it is a safe root-relative path on this origin, else `/`.
 *
 * Must reject: absolute/protocol-relative URLs (`//evil`, `https://evil`) AND
 * backslash variants (`/\evil`, `/\/evil`) — browsers normalize `\` to `/` in a
 * `Location` header, so `/\evil.com` becomes `//evil.com` → an off-origin
 * redirect. Also reject control characters.
 */
export declare function safeReturnTo(raw: string | undefined | null): string;
export declare function registerOAuthApiRoutes(fastify: FastifyInstance, authService: AuthService, workspaceConfig: WorkspaceConfigLike): Promise<void>;
export {};
