/** * OAuth 2.1 authorization endpoint — /oauth/authorize * * The "front door" for the authorization_code grant required by Anthropic * Claude.ai connectors. This is a stateless consent screen, not a login * page: HemmaBo's identity model is guest-without-identity (ADR 0003 §2.1). * The end user sees one button — "Connect HemmaBo to Claude" — and clicking * it issues a single-use authorization code that the AI client then redeems * at /oauth/token together with the PKCE verifier. * * Flow per RFC 6749 §4.1 + RFC 7636 + ADR 0003: * * GET /oauth/authorize?response_type=code&client_id=...&redirect_uri=... * &state=...&code_challenge=...&code_challenge_method=S256&scope=mcp * * Validate every parameter. Anti-open-redirect: if redirect_uri is not * in the client's allowlist, render the error page in-place. NEVER * redirect to an unverified URI. Other errors round-trip via the * redirect_uri so the client can see them per RFC 6749 §4.1.2.1. * * On success render a minimal HTML page with an "Approve" form that * POSTs back to this same endpoint with the same parameters echoed in * hidden inputs. * * POST /oauth/authorize * * Re-validate (state is not trusted), insert mcp_authorization_codes * row (10-min TTL, single-use, S256), and 302-redirect to * `${redirect_uri}?code=&state=`. * * No authentication is required to reach this endpoint — the user is, by * definition, anonymous until they consent. Rate-limit (strict tier) keys * on source IP to deter code-grinding probes. */ import type { VercelRequest, VercelResponse } from "./_types.js"; export default function handler(req: VercelRequest, res: VercelResponse): Promise;