@ractive-ch/tab-mcp 0.1.0-alpha.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -0
- package/index.d.ts +1 -1
- package/index.js +13 -13
- package/index.js.map +6 -6
- package/main.js +13 -13
- package/main.js.map +6 -6
- package/package.json +1 -1
package/index.js.map
CHANGED
|
@@ -8,18 +8,18 @@
|
|
|
8
8
|
"import type { LogLevel } from \"./config.ts\";\nimport { parseIpv4, parseIpv6 } from \"./ip.ts\";\n\n/**\n * Structured JSON-line logging (threat model A9). Callers pass only metadata:\n * never request or response bodies, tool names, arguments, results, tokens,\n * pairing codes or page secrets. There is deliberately no helper that accepts\n * a body.\n */\n\nexport type LogFields = Record<string, string | number | boolean | null>;\n\nexport interface Logger {\n\terror(event: string, fields?: LogFields): void;\n\twarn(event: string, fields?: LogFields): void;\n\tinfo(event: string, fields?: LogFields): void;\n\tdebug(event: string, fields?: LogFields): void;\n}\n\nconst ORDER: Record<LogLevel, number> = {\n\terror: 0,\n\twarn: 1,\n\tinfo: 2,\n\tdebug: 3,\n};\n\n/** A logger that writes one JSON object per line to `sink` (stdout by default). */\nexport function createLogger(\n\tlevel: LogLevel,\n\tsink: (line: string) => void = (line) => {\n\t\tprocess.stdout.write(`${line}\\n`);\n\t},\n): Logger {\n\tconst max = ORDER[level];\n\tconst write = (lvl: LogLevel, event: string, fields?: LogFields) => {\n\t\tif (ORDER[lvl] > max) return;\n\t\tsink(\n\t\t\tJSON.stringify({\n\t\t\t\ttime: new Date().toISOString(),\n\t\t\t\tlevel: lvl,\n\t\t\t\tevent,\n\t\t\t\t...fields,\n\t\t\t}),\n\t\t);\n\t};\n\treturn {\n\t\terror: (e, f) => write(\"error\", e, f),\n\t\twarn: (e, f) => write(\"warn\", e, f),\n\t\tinfo: (e, f) => write(\"info\", e, f),\n\t\tdebug: (e, f) => write(\"debug\", e, f),\n\t};\n}\n\n/**\n * Truncate an IP for logs: IPv4 to /24, IPv6 to /48. IPv4-mapped IPv6\n * (`::ffff:a.b.c.d`) is treated as IPv4. `?` if it does not parse.\n */\nexport function truncateIp(ip: string): string {\n\tconst v4 = parseIpv4(ip);\n\tif (v4 !== undefined) return `${v4.slice(0, 3).join(\".\")}.0/24`;\n\tconst v6 = parseIpv6(ip);\n\tif (v6 === undefined) return \"?\";\n\tconst mapped = v6.slice(0, 5).every((g) => g === 0) && v6[5] === 0xffff;\n\tif (mapped) {\n\t\tconst hi = v6[6] ?? 0;\n\t\treturn `${hi >> 8}.${hi & 0xff}.${(v6[7] ?? 0) >> 8}.0/24`;\n\t}\n\treturn `${v6\n\t\t.slice(0, 3)\n\t\t.map((g) => g.toString(16))\n\t\t.join(\":\")}::/48`;\n}\n\n/**\n * Defence in depth (DEC-047). The relay catches errors per message and per\n * request; anything that still escapes is logged, never silently fatal:\n * - an unhandled promise rejection is logged and the relay keeps running, so one\n * bad request or tab cannot end every other session;\n * - an uncaught exception is logged and the process exits with 1, because the\n * relay's state may be inconsistent; the supervisor (Docker, systemd) restarts\n * it and AI apps keep their tokens (they live in the store).\n * Only the error's name is logged: messages can carry request data.\n * Returns a function that removes the handlers.\n */\nexport function installCrashLogging(\n\tlogger: Logger,\n\texit: (code: number) => void = (code) => process.exit(code),\n): () => void {\n\tconst name = (error: unknown) =>\n\t\terror instanceof Error ? error.name : typeof error;\n\tconst onRejection = (error: unknown) => {\n\t\tlogger.error(\"process.unhandled_rejection\", { error: name(error) });\n\t};\n\tconst onException = (error: unknown) => {\n\t\tlogger.error(\"process.uncaught_exception\", { error: name(error) });\n\t\texit(1);\n\t};\n\tprocess.on(\"unhandledRejection\", onRejection);\n\tprocess.on(\"uncaughtException\", onException);\n\treturn () => {\n\t\tprocess.off(\"unhandledRejection\", onRejection);\n\t\tprocess.off(\"uncaughtException\", onException);\n\t};\n}\n",
|
|
9
9
|
"/**\n * The tab↔relay protocol, version 1 (`tab-mcp.v1`).\n *\n * One WebSocket per tab session; text frames with one JSON object each. The\n * normative description is `kb/design/protocol.md` (later `docs/protocol.md`).\n */\n\nimport { isAppName, MAX_APP_NAME } from \"./config.ts\";\n\nexport const SUBPROTOCOL = \"tab-mcp.v1\";\n\n/** The only MCP revision the relay serves (DEC-033). */\nexport const MCP_PROTOCOL_VERSION = \"2026-07-28\";\n\n/** `_meta` key that carries the protocol version in every 2026-07-28 request. */\nexport const PROTOCOL_VERSION_META_KEY =\n\t\"io.modelcontextprotocol/protocolVersion\";\n\nexport const CloseCode = {\n\tnormal: 1000,\n\tpolicyViolation: 1008,\n\ttooLarge: 1009,\n\tsessionExpired: 4001,\n\tidleTimeout: 4002,\n\theartbeatLost: 4003,\n\tshuttingDown: 4004,\n\treplaced: 4005,\n\trateLimited: 4008,\n} as const;\n\nexport type ByeReason = \"replaced\" | \"expired\" | \"idle\" | \"shutdown\" | \"user\";\n\nexport interface Limits {\n\tmaxMessageBytes: number;\n\tmaxBodyBytes: number;\n\trequestTimeoutMs: number;\n\tidleTimeoutMs: number;\n\theartbeatMs: number;\n\tkeepAliveMs: number;\n\tmaxConcurrentRequests: number;\n}\n\n/** Who is calling, as the tab sees it (passed to the MCP handler as `authInfo`). */\nexport interface GrantRef {\n\tgrantId: string;\n\tclientId: string;\n\tscopes: string[];\n}\n\n/** A connected AI app as listed to the tab. */\nexport interface GrantInfo {\n\tgrantId: string;\n\tclient: { id: string; name: string; host: string };\n\tcreatedAt: string;\n}\n\n// Relay → tab\n\nexport interface SessionMessage {\n\ttype: \"session\";\n\tsessionId: string;\n\taddress: string;\n\torigin: string;\n\t/** The name `/authorize` shows: the site's configured name, else the page's. */\n\tappName?: string;\n\texpiresAt: string;\n\tlimits: Limits;\n\tgrants: GrantInfo[];\n}\nexport interface PingMessage {\n\ttype: \"ping\";\n\tt: number;\n}\nexport interface ByeMessage {\n\ttype: \"bye\";\n\treason: string;\n}\nexport interface HttpRequestMessage {\n\ttype: \"http.request\";\n\tid: string;\n\tmethod: string;\n\tpath: string;\n\theaders: Record<string, string>;\n\tbody: string;\n\tgrant: GrantRef;\n}\nexport interface HttpCancelMessage {\n\ttype: \"http.cancel\";\n\tid: string;\n\treason: \"client_closed\" | \"timeout\" | \"error\";\n}\nexport interface PairingCodeMessage {\n\ttype: \"pairing.code\";\n\tcode: string;\n\texpiresAt: string;\n}\nexport interface GrantAddedMessage {\n\ttype: \"grant.added\";\n\tgrant: GrantInfo;\n}\nexport interface GrantRemovedMessage {\n\ttype: \"grant.removed\";\n\tgrantId: string;\n\treason: \"revoked\" | \"reuse_detected\" | \"expired\";\n}\nexport interface ErrorMessage {\n\ttype: \"error\";\n\tcode: ErrorCode;\n\tmessage: string;\n\tid?: string;\n}\nexport type RelayMessage =\n\t| SessionMessage\n\t| PingMessage\n\t| ByeMessage\n\t| HttpRequestMessage\n\t| HttpCancelMessage\n\t| PairingCodeMessage\n\t| GrantAddedMessage\n\t| GrantRemovedMessage\n\t| ErrorMessage;\n\nexport type ErrorCode =\n\t| \"bad_message\"\n\t| \"unknown_type\"\n\t| \"unknown_id\"\n\t| \"too_large\"\n\t| \"rate_limited\";\n\n// Tab → relay\n\nexport interface HelloMessage {\n\ttype: \"hello\";\n\tlibrary: { name: string; version: string };\n\tpage: { title: string };\n\t/** Self-declared app name (DEC-045), unverified. */\n\tapp?: { name: string };\n\tsecret: string;\n}\nexport interface PongMessage {\n\ttype: \"pong\";\n\tt: number;\n}\nexport interface HttpResponseMessage {\n\ttype: \"http.response\";\n\tid: string;\n\tstatus: number;\n\theaders: Record<string, string>;\n\tbody: string;\n}\nexport interface HttpResponseStartMessage {\n\ttype: \"http.response.start\";\n\tid: string;\n\tstatus: number;\n\theaders: Record<string, string>;\n}\nexport interface HttpResponseChunkMessage {\n\ttype: \"http.response.chunk\";\n\tid: string;\n\tdata: string;\n}\nexport interface HttpResponseEndMessage {\n\ttype: \"http.response.end\";\n\tid: string;\n}\nexport interface TabErrorMessage {\n\ttype: \"error\";\n\tcode: string;\n\tmessage: string;\n\tid?: string;\n}\nexport interface PairingStartMessage {\n\ttype: \"pairing.start\";\n}\nexport interface PairingStopMessage {\n\ttype: \"pairing.stop\";\n}\nexport interface GrantRevokeMessage {\n\ttype: \"grant.revoke\";\n\tgrantId: string;\n}\nexport interface GrantsRevokeAllMessage {\n\ttype: \"grants.revokeAll\";\n}\nexport type TabMessage =\n\t| HelloMessage\n\t| PairingStartMessage\n\t| PairingStopMessage\n\t| GrantRevokeMessage\n\t| GrantsRevokeAllMessage\n\t| PongMessage\n\t| ByeMessage\n\t| HttpResponseMessage\n\t| HttpResponseStartMessage\n\t| HttpResponseChunkMessage\n\t| HttpResponseEndMessage\n\t| TabErrorMessage;\n\n/** Result of parsing one frame from the tab. */\nexport type ParseResult =\n\t| { ok: true; message: TabMessage }\n\t/** A well-formed message of a type this relay does not know. */\n\t| { ok: true; unknown: true; type: string; id?: string }\n\t| { ok: false; error: string; id?: string };\n\nconst MAX_TITLE = 300;\nconst MAX_NAME = 200;\nconst MAX_ID = 128;\nconst MAX_HEADER_COUNT = 32;\nconst MAX_HEADER_VALUE = 8192;\n\n/**\n * RFC 9110 §5.5 field value: visible ASCII, obs-text (0x80-0xFF), space and\n * tab; no other control characters (CR, LF, NUL, DEL, …) and nothing beyond\n * 0xFF, which `Headers` would reject.\n */\nconst FIELD_VALUE = /^[\\t\\x20-\\x7E\\x80-\\xFF]*$/;\n\ntype Json = Record<string, unknown>;\n\nfunction isObject(v: unknown): v is Json {\n\treturn typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction isString(v: unknown, max: number): v is string {\n\treturn typeof v === \"string\" && v.length <= max;\n}\n\nfunction isId(v: unknown): v is string {\n\treturn typeof v === \"string\" && v.length > 0 && v.length <= MAX_ID;\n}\n\nfunction isStatus(v: unknown): v is number {\n\treturn typeof v === \"number\" && Number.isInteger(v) && v >= 200 && v <= 599;\n}\n\nfunction isHeaders(v: unknown): v is Record<string, string> {\n\tif (!isObject(v)) return false;\n\tconst entries = Object.entries(v);\n\tif (entries.length > MAX_HEADER_COUNT) return false;\n\treturn entries.every(\n\t\t([k, val]) =>\n\t\t\t/^[a-z0-9-]{1,64}$/.test(k) &&\n\t\t\tisString(val, MAX_HEADER_VALUE) &&\n\t\t\tFIELD_VALUE.test(val),\n\t);\n}\n\nfunction idOf(v: Json): string | undefined {\n\treturn isId(v[\"id\"]) ? v[\"id\"] : undefined;\n}\n\n/**\n * Parse and validate one text frame from the tab. Hand-written on purpose: the\n * relay has no schema library (DEC-014).\n */\nexport function parseTabMessage(text: string): ParseResult {\n\tlet v: unknown;\n\ttry {\n\t\tv = JSON.parse(text);\n\t} catch {\n\t\treturn { ok: false, error: \"not JSON\" };\n\t}\n\tif (!isObject(v)) return { ok: false, error: \"not a JSON object\" };\n\tconst type = v[\"type\"];\n\tif (typeof type !== \"string\" || type.length === 0 || type.length > 64) {\n\t\treturn { ok: false, error: \"missing type\" };\n\t}\n\tconst id = idOf(v);\n\tconst bad = (error: string): ParseResult =>\n\t\tid === undefined ? { ok: false, error } : { ok: false, error, id };\n\n\tswitch (type) {\n\t\tcase \"hello\": {\n\t\t\tconst library = v[\"library\"];\n\t\t\tconst page = v[\"page\"];\n\t\t\tif (\n\t\t\t\t!isObject(library) ||\n\t\t\t\t!isString(library[\"name\"], MAX_NAME) ||\n\t\t\t\t!isString(library[\"version\"], MAX_NAME)\n\t\t\t) {\n\t\t\t\treturn bad(\"hello.library must be {name, version}\");\n\t\t\t}\n\t\t\tif (!isObject(page) || !isString(page[\"title\"], MAX_TITLE)) {\n\t\t\t\treturn bad(\"hello.page must be {title}\");\n\t\t\t}\n\t\t\tif (typeof v[\"secret\"] !== \"string\") return bad(\"hello.secret missing\");\n\t\t\tconst app = v[\"app\"];\n\t\t\tif (app !== undefined && (!isObject(app) || !isAppName(app[\"name\"]))) {\n\t\t\t\treturn bad(`hello.app.name must be 1-${MAX_APP_NAME} characters`);\n\t\t\t}\n\t\t\tconst hello: HelloMessage = {\n\t\t\t\ttype,\n\t\t\t\tlibrary: { name: library[\"name\"], version: library[\"version\"] },\n\t\t\t\tpage: { title: page[\"title\"] },\n\t\t\t\tsecret: v[\"secret\"],\n\t\t\t};\n\t\t\tif (isObject(app) && isAppName(app[\"name\"])) {\n\t\t\t\thello.app = { name: app[\"name\"] };\n\t\t\t}\n\t\t\treturn { ok: true, message: hello };\n\t\t}\n\t\tcase \"pong\": {\n\t\t\tconst t = v[\"t\"];\n\t\t\tif (typeof t !== \"number\") return bad(\"pong.t must be a number\");\n\t\t\treturn { ok: true, message: { type, t } };\n\t\t}\n\t\tcase \"bye\": {\n\t\t\tconst reason = v[\"reason\"];\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\tmessage: {\n\t\t\t\t\ttype,\n\t\t\t\t\treason: isString(reason, MAX_NAME) ? reason : \"\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tcase \"http.response\": {\n\t\t\tif (id === undefined) return bad(\"http.response.id missing\");\n\t\t\tconst { status, headers, body } = v;\n\t\t\tif (!isStatus(status)) return bad(\"http.response.status invalid\");\n\t\t\tif (!isHeaders(headers)) return bad(\"http.response.headers invalid\");\n\t\t\tif (typeof body !== \"string\") return bad(\"http.response.body invalid\");\n\t\t\treturn { ok: true, message: { type, id, status, headers, body } };\n\t\t}\n\t\tcase \"http.response.start\": {\n\t\t\tif (id === undefined) return bad(\"http.response.start.id missing\");\n\t\t\tconst { status, headers } = v;\n\t\t\tif (!isStatus(status)) return bad(\"http.response.start.status invalid\");\n\t\t\tif (!isHeaders(headers))\n\t\t\t\treturn bad(\"http.response.start.headers invalid\");\n\t\t\treturn { ok: true, message: { type, id, status, headers } };\n\t\t}\n\t\tcase \"http.response.chunk\": {\n\t\t\tif (id === undefined) return bad(\"http.response.chunk.id missing\");\n\t\t\tconst data = v[\"data\"];\n\t\t\tif (typeof data !== \"string\")\n\t\t\t\treturn bad(\"http.response.chunk.data invalid\");\n\t\t\treturn { ok: true, message: { type, id, data } };\n\t\t}\n\t\tcase \"http.response.end\": {\n\t\t\tif (id === undefined) return bad(\"http.response.end.id missing\");\n\t\t\treturn { ok: true, message: { type, id } };\n\t\t}\n\t\tcase \"pairing.start\":\n\t\tcase \"pairing.stop\":\n\t\tcase \"grants.revokeAll\":\n\t\t\treturn { ok: true, message: { type } };\n\t\tcase \"grant.revoke\": {\n\t\t\tconst grantId = v[\"grantId\"];\n\t\t\tif (!isId(grantId)) return bad(\"grant.revoke.grantId missing\");\n\t\t\treturn { ok: true, message: { type, grantId } };\n\t\t}\n\t\tcase \"error\": {\n\t\t\tconst code = v[\"code\"];\n\t\t\tconst message = v[\"message\"];\n\t\t\tif (!isString(code, MAX_NAME)) return bad(\"error.code invalid\");\n\t\t\tconst m: TabErrorMessage = {\n\t\t\t\ttype,\n\t\t\t\tcode,\n\t\t\t\tmessage: isString(message, 1000) ? message : \"\",\n\t\t\t};\n\t\t\tif (id !== undefined) m.id = id;\n\t\t\treturn { ok: true, message: m };\n\t\t}\n\t\tdefault:\n\t\t\treturn id === undefined\n\t\t\t\t? { ok: true, unknown: true, type }\n\t\t\t\t: { ok: true, unknown: true, type, id };\n\t}\n}\n",
|
|
10
10
|
"import type {\n\tHttpResponseMessage,\n\tHttpResponseStartMessage,\n} from \"./protocol.ts\";\n\n/**\n * One tunnelled MCP request: the AI app's HTTP response, built from the tab's\n * `http.response*` messages, with the request timer, SSE keep-alives (DEC-020)\n * and the relay-started event stream (DEC-039).\n */\n\nexport type RpcId = string | number | null;\n\n/** JSON-RPC error codes the relay itself uses (outside the reserved range). */\nexport const RelayErrorCode = {\n\tpageNotOpen: -31001,\n\ttimeout: -31002,\n\ttabGone: -31003,\n\toverloaded: -31004,\n\tsendFailed: -31005,\n\ttooLarge: -31006,\n\tbadResponse: -31007,\n\tstoreUnavailable: -31008,\n} as const;\n\nexport type CancelReason = \"client_closed\" | \"timeout\" | \"error\";\n\nexport interface ExchangeOptions {\n\tid: string;\n\t/** JSON-RPC id of the request; `undefined` for a notification. */\n\trpcId: RpcId | undefined;\n\t/** `subscriptions/listen`: exempt from the request timer. */\n\tisListen: boolean;\n\trequestTimeoutMs: number;\n\tkeepAliveMs: number;\n\t/**\n\t * Limit for the response body the tab sends (not for listen streams), and\n\t * the bound for bytes queued towards an AI app that does not read.\n\t */\n\tmaxBodyBytes: number;\n\t/** Extra headers for every response (CORS). */\n\textraHeaders: Record<string, string>;\n\t/** Tell the tab to stop working on this request. */\n\tcancel: (reason: CancelReason) => void;\n\t/** Called once when the exchange is over. */\n\tonDone: (exchange: Exchange) => void;\n}\n\nconst encoder = new TextEncoder();\n\n/** Statuses that must not carry a body (Fetch \"null body status\", 101/103 excluded by the parser). */\nconst NULL_BODY_STATUSES = new Set([204, 205, 304]);\n\n/** Response headers the relay passes on from the tab. */\nconst PASSED_RESPONSE_HEADERS = new Set([\"content-type\", \"cache-control\"]);\n\nfunction isEventStream(headers: Record<string, string>): boolean {\n\treturn (headers[\"content-type\"] ?? \"\")\n\t\t.toLowerCase()\n\t\t.startsWith(\"text/event-stream\");\n}\n\nfunction endsAtBoundary(text: string): boolean {\n\treturn (\n\t\ttext.endsWith(\"\\n\\n\") || text.endsWith(\"\\r\\n\\r\\n\") || text.endsWith(\"\\r\\r\")\n\t);\n}\n\n/** One SSE `message` event carrying `data` (split into `data:` lines). */\nexport function sseEvent(data: string): string {\n\tconst lines = data.split(/\\r\\n|\\r|\\n/);\n\treturn `event: message\\n${lines.map((l) => `data: ${l}`).join(\"\\n\")}\\n\\n`;\n}\n\nexport function rpcErrorBody(\n\trpcId: RpcId | undefined,\n\tcode: number,\n\tmessage: string,\n\tdata?: unknown,\n): string {\n\tconst error: Record<string, unknown> = { code, message };\n\tif (data !== undefined) error[\"data\"] = data;\n\treturn JSON.stringify({ jsonrpc: \"2.0\", id: rpcId ?? null, error });\n}\n\nexport class Exchange {\n\treadonly id: string;\n\treadonly isListen: boolean;\n\treadonly response: Promise<Response>;\n\t/** HTTP status sent to the AI app (for logs); 0 while waiting. */\n\tstatus = 0;\n\t/** How the exchange ended (for logs). */\n\toutcome = \"pending\";\n\t/** Why the tab's response was refused, for the tab's `error` message. */\n\tbadResponseReason: string | undefined;\n\n\treadonly #options: ExchangeOptions;\n\t#resolve!: (response: Response) => void;\n\t#state: \"waiting\" | \"streaming\" | \"done\" = \"waiting\";\n\t/** The relay started the stream; a tab `http.response` becomes one event. */\n\t#relayStarted = false;\n\t/** The tab sent `http.response.start`: only chunks and the end may follow. */\n\t#tabStarted = false;\n\t/** Buffer a non-SSE streamed body to send it as one event. */\n\t#wrap = false;\n\t#wrapped = \"\";\n\t#controller: ReadableStreamDefaultController<Uint8Array> | undefined;\n\t#atBoundary = true;\n\t/** Response body bytes received from the tab so far. */\n\t#bodyBytes = 0;\n\t#startTimer: Timer | undefined;\n\t#requestTimer: Timer | undefined;\n\t#keepAliveTimer: Timer | undefined;\n\n\tconstructor(options: ExchangeOptions) {\n\t\tthis.#options = options;\n\t\tthis.id = options.id;\n\t\tthis.isListen = options.isListen;\n\t\tthis.response = new Promise((resolve) => {\n\t\t\tthis.#resolve = resolve;\n\t\t});\n\t\tif (options.rpcId !== undefined) {\n\t\t\tthis.#startTimer = setTimeout(\n\t\t\t\t() => this.#startRelayStream(),\n\t\t\t\toptions.keepAliveMs,\n\t\t\t);\n\t\t}\n\t\tif (!options.isListen) {\n\t\t\tthis.#requestTimer = setTimeout(\n\t\t\t\t() => this.#timeout(),\n\t\t\t\toptions.requestTimeoutMs,\n\t\t\t);\n\t\t}\n\t}\n\n\tget done(): boolean {\n\t\treturn this.#state === \"done\";\n\t}\n\n\t/** A complete response from the tab. */\n\tonResponse(msg: HttpResponseMessage): void {\n\t\tif (this.#tabStarted) {\n\t\t\tthis.#badResponse(\"http.response after http.response.start\");\n\t\t\treturn;\n\t\t}\n\t\tif (this.#state === \"waiting\") {\n\t\t\tif (!this.#account(msg.body)) return;\n\t\t\tif (NULL_BODY_STATUSES.has(msg.status) && msg.body !== \"\") {\n\t\t\t\tthis.#badResponse(`status ${msg.status} must not have a body`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet response: Response;\n\t\t\ttry {\n\t\t\t\tresponse = new Response(msg.body === \"\" ? null : msg.body, {\n\t\t\t\t\tstatus: msg.status,\n\t\t\t\t\theaders: this.#headers(msg.headers),\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tthis.#badResponse(\"the response could not be built\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.#respond(response, msg.status);\n\t\t\tthis.#finish(\"ok\");\n\t\t} else if (this.#state === \"streaming\" && this.#relayStarted) {\n\t\t\tif (!this.#account(msg.body)) return;\n\t\t\tif (msg.body !== \"\") this.#write(sseEvent(msg.body));\n\t\t\tthis.#finish(\"ok\");\n\t\t}\n\t}\n\n\tonStart(msg: HttpResponseStartMessage): void {\n\t\tif (this.#tabStarted) {\n\t\t\tthis.#badResponse(\"http.response.start sent twice\");\n\t\t\treturn;\n\t\t}\n\t\tthis.#tabStarted = true;\n\t\tif (this.#state === \"waiting\") {\n\t\t\tif (NULL_BODY_STATUSES.has(msg.status)) {\n\t\t\t\tthis.#badResponse(`status ${msg.status} cannot be streamed`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet headers: Headers;\n\t\t\ttry {\n\t\t\t\theaders = this.#headers(msg.headers);\n\t\t\t} catch {\n\t\t\t\tthis.#badResponse(\"the response headers are invalid\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.#openStream(msg.status, headers);\n\t\t} else if (this.#state === \"streaming\" && this.#relayStarted) {\n\t\t\tthis.#wrap = !isEventStream(msg.headers);\n\t\t}\n\t}\n\n\tonChunk(data: string): void {\n\t\tif (this.#state !== \"streaming\") return;\n\t\tif (!this.#account(data)) return;\n\t\tif (this.#wrap) this.#wrapped += data;\n\t\telse this.#write(data);\n\t}\n\n\tonEnd(): void {\n\t\tif (this.#state !== \"streaming\") return;\n\t\tif (this.#wrap && this.#wrapped !== \"\")\n\t\t\tthis.#write(sseEvent(this.#wrapped));\n\t\tthis.#finish(\"ok\");\n\t}\n\n\t/** The AI app went away: tell the tab, send nothing more. */\n\tclientClosed(): void {\n\t\tif (this.#state === \"done\") return;\n\t\tif (this.#state === \"waiting\")\n\t\t\tthis.#respond(new Response(null, { status: 503 }), 0);\n\t\tthis.#options.cancel(\"client_closed\");\n\t\tthis.#finish(\"client_closed\", false);\n\t}\n\n\t/**\n\t * End the exchange with an error the AI app can read: an HTTP error while\n\t * nothing was sent, else a JSON-RPC error event if the stream is at an\n\t * event boundary.\n\t */\n\tfail(\n\t\tstatus: number,\n\t\tcode: number,\n\t\tmessage: string,\n\t\tcancelTab: boolean,\n\t): void {\n\t\tif (this.#state === \"done\") return;\n\t\tif (this.#state === \"waiting\") {\n\t\t\tthis.#respond(this.#errorResponse(status, code, message), status);\n\t\t} else if (this.#atBoundary && this.#options.rpcId !== undefined) {\n\t\t\tthis.#write(sseEvent(rpcErrorBody(this.#options.rpcId, code, message)));\n\t\t}\n\t\tif (cancelTab) this.#options.cancel(\"error\");\n\t\tthis.#finish(`error_${code}`);\n\t}\n\n\t/**\n\t * The tab sent a response the relay cannot pass on: 502 to the AI app (or an\n\t * error event), cancel the tab's work. `reason` goes to the tab, not the app.\n\t */\n\t#badResponse(reason: string): void {\n\t\tthis.badResponseReason = reason;\n\t\tthis.fail(\n\t\t\t502,\n\t\t\tRelayErrorCode.badResponse,\n\t\t\t\"The page sent an invalid response.\",\n\t\t\ttrue,\n\t\t);\n\t}\n\n\t/**\n\t * Count response bytes from the tab; past `maxBodyBytes` (listen streams\n\t * excepted) fail with 502 / -31006 and cancel the tab. False when failed.\n\t */\n\t#account(data: string): boolean {\n\t\tthis.#bodyBytes += Buffer.byteLength(data);\n\t\tif (this.isListen || this.#bodyBytes <= this.#options.maxBodyBytes) {\n\t\t\treturn true;\n\t\t}\n\t\tthis.fail(\n\t\t\t502,\n\t\t\tRelayErrorCode.tooLarge,\n\t\t\t\"The page sent a response that is too large.\",\n\t\t\ttrue,\n\t\t);\n\t\treturn false;\n\t}\n\n\t#timeout(): void {\n\t\tif (this.#state === \"done\") return;\n\t\tthis.fail(\n\t\t\t504,\n\t\t\tRelayErrorCode.timeout,\n\t\t\t\"The page did not answer in time.\",\n\t\t\tfalse,\n\t\t);\n\t\tthis.#options.cancel(\"timeout\");\n\t}\n\n\t#startRelayStream(): void {\n\t\tif (this.#state !== \"waiting\") return;\n\t\tthis.#relayStarted = true;\n\t\tthis.#openStream(\n\t\t\t200,\n\t\t\tthis.#headers({ \"content-type\": \"text/event-stream\" }),\n\t\t);\n\t}\n\n\t#openStream(status: number, headers: Headers): void {\n\t\t// Bounded queue: if the AI app stops reading, desiredSize goes negative\n\t\t// once maxBodyBytes are queued, and the exchange ends (see #write).\n\t\tconst stream = new ReadableStream<Uint8Array>(\n\t\t\t{\n\t\t\t\tstart: (controller) => {\n\t\t\t\t\tthis.#controller = controller;\n\t\t\t\t},\n\t\t\t\tcancel: () => this.clientClosed(),\n\t\t\t},\n\t\t\tnew ByteLengthQueuingStrategy({\n\t\t\t\thighWaterMark: this.#options.maxBodyBytes,\n\t\t\t}),\n\t\t);\n\t\tif (isEventStream(Object.fromEntries(headers))) {\n\t\t\theaders.set(\"x-accel-buffering\", \"no\");\n\t\t\tif (!headers.has(\"cache-control\"))\n\t\t\t\theaders.set(\"cache-control\", \"no-cache\");\n\t\t}\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = new Response(stream, { status, headers });\n\t\t} catch {\n\t\t\tthis.#badResponse(\"the response could not be built\");\n\t\t\treturn;\n\t\t}\n\t\tthis.#state = \"streaming\";\n\t\tthis.#respond(response, status);\n\t\tthis.#scheduleKeepAlive();\n\t}\n\n\t#write(text: string): void {\n\t\tif (\n\t\t\tthis.#state !== \"streaming\" ||\n\t\t\tthis.#controller === undefined ||\n\t\t\ttext === \"\"\n\t\t)\n\t\t\treturn;\n\t\ttry {\n\t\t\tthis.#controller.enqueue(encoder.encode(text));\n\t\t} catch {\n\t\t\tthis.clientClosed();\n\t\t\treturn;\n\t\t}\n\t\tthis.#atBoundary = endsAtBoundary(text);\n\t\tconst room = this.#controller.desiredSize;\n\t\tif (room !== null && room < 0) {\n\t\t\t// The AI app is not reading: stop the tab, drop the stream. No error\n\t\t\t// event, since nothing more would reach the reader anyway.\n\t\t\tthis.#options.cancel(\"error\");\n\t\t\tthis.#finish(\"backpressure\");\n\t\t\treturn;\n\t\t}\n\t\tthis.#scheduleKeepAlive();\n\t}\n\n\t/** A keep-alive comment `keepAliveMs` after the last write, at a boundary. */\n\t#scheduleKeepAlive(): void {\n\t\tclearTimeout(this.#keepAliveTimer);\n\t\tif (this.#state !== \"streaming\" || this.#wrap) {\n\t\t\tif (this.#state === \"streaming\") {\n\t\t\t\tthis.#keepAliveTimer = setTimeout(() => {\n\t\t\t\t\t// While buffering a wrapped body nothing has been forwarded since\n\t\t\t\t\t// the last boundary, so a comment is safe.\n\t\t\t\t\tthis.#write(\": keep-alive\\n\\n\");\n\t\t\t\t}, this.#options.keepAliveMs);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tthis.#keepAliveTimer = setTimeout(() => {\n\t\t\tif (this.#atBoundary) this.#write(\": keep-alive\\n\\n\");\n\t\t\telse this.#scheduleKeepAlive();\n\t\t}, this.#options.keepAliveMs);\n\t}\n\n\t#headers(fromTab: Record<string, string>): Headers {\n\t\tconst headers = new Headers(this.#options.extraHeaders);\n\t\tfor (const [k, v] of Object.entries(fromTab)) {\n\t\t\tif (PASSED_RESPONSE_HEADERS.has(k)) headers.set(k, v);\n\t\t}\n\t\treturn headers;\n\t}\n\n\t#errorResponse(status: number, code: number, message: string): Response {\n\t\tconst headers = this.#headers({ \"content-type\": \"application/json\" });\n\t\treturn new Response(rpcErrorBody(this.#options.rpcId, code, message), {\n\t\t\tstatus,\n\t\t\theaders,\n\t\t});\n\t}\n\n\t#respond(response: Response, status: number): void {\n\t\tclearTimeout(this.#startTimer);\n\t\tthis.status = status;\n\t\tthis.#resolve(response);\n\t}\n\n\t#finish(outcome: string, closeStream = true): void {\n\t\tif (this.#state === \"done\") return;\n\t\tconst wasStreaming = this.#state === \"streaming\";\n\t\tthis.#state = \"done\";\n\t\tthis.outcome = outcome;\n\t\tclearTimeout(this.#startTimer);\n\t\tclearTimeout(this.#requestTimer);\n\t\tclearTimeout(this.#keepAliveTimer);\n\t\tif (wasStreaming && closeStream) {\n\t\t\ttry {\n\t\t\t\tthis.#controller?.close();\n\t\t\t} catch {\n\t\t\t\t// already closed by the client\n\t\t\t}\n\t\t}\n\t\tthis.#options.onDone(this);\n\t}\n}\n",
|
|
11
|
-
"/**\n * The relay's OAuth 2.1 authorization server (DEC-006, DEC-015, DEC-031),\n * written without an OAuth library:\n *\n * - RFC 9728 protected-resource metadata per address, RFC 8414 server metadata;\n * - clients only through Client ID Metadata Documents (`cimd.ts`);\n * - `/authorize` with PKCE S256 only, exact redirect URIs (loopback port\n * relaxed), `resource` bound to one address (RFC 8707), `iss` in every\n * response (RFC 9207), and the pairing step of the address's site (DEC-042);\n * - `/token` for the authorization code and rotating refresh tokens (DEC-029);\n * - `/revoke` (RFC 7009).\n */\n\nimport { timingSafeEqual } from \"node:crypto\";\nimport { isAddressId, shortAddress } from \"../address.ts\";\nimport type { PairingKind, RelayConfig, Site } from \"../config.ts\";\nimport type { Logger } from \"../log.ts\";\nimport type { GrantInfo } from \"../protocol.ts\";\nimport { RateLimiter } from \"../ratelimit.ts\";\nimport type { TokenRecord, TokenStore } from \"../store/types.ts\";\nimport { hashToken, issueTokenPair, newId } from \"../tokens.ts\";\nimport {\n\ttype CimdTestMode,\n\ttype ClientMetadata,\n\tClientMetadataError,\n\tClientMetadataFetcher,\n\tredirectUriMatches,\n} from \"./cimd.ts\";\nimport { AUTHORIZE_CSS, escapeHtml, pageHeaders, renderPage } from \"./html.ts\";\nimport {\n\tPAIRING_METHODS,\n\ttype PairingMethod,\n\ttype PairingTarget,\n} from \"./pairing.ts\";\n\n/** The only scope: calling the page's tools. */\nexport const SCOPE = \"tools\";\n\n/** How long a user has to finish the `/authorize` page. */\nconst PENDING_TTL_MS = 10 * 60_000;\n/** Authorization codes are single-use and short-lived (RFC 6749 §4.1.2). */\nconst AUTH_CODE_TTL_MS = 60_000;\nconst MAX_PENDING = 10_000;\n/** Open authorization requests per IP (prefix) and per address (DEC-061). */\nconst MAX_PENDING_PER_IP = 10;\nconst MAX_PENDING_PER_ADDRESS = 20;\nconst MAX_CODES = 10_000;\nconst MAX_FORM_BYTES = 8192;\nconst MAX_STATE_LENGTH = 1024;\n\n/** A tab session as the authorization server sees it. */\nexport interface AuthorizeSession extends PairingTarget {\n\treadonly origin: string;\n\treadonly appName: string | undefined;\n\treadonly site: Site;\n}\n\nexport interface AuthorizationHost {\n\treadonly config: RelayConfig;\n\treadonly logger: Logger;\n\treadonly store: TokenStore;\n\tpublicUrl(): string;\n\t/** The connected (ready) tab session of an address. */\n\tsession(addressId: string): AuthorizeSession | undefined;\n\t/** Tell the address's tab, if connected. */\n\tgrantAdded(addressId: string, grant: GrantInfo): void;\n\tgrantRemoved(addressId: string, grantId: string, reason: string): void;\n}\n\n/** Test-only settings; never reachable from configuration. */\nexport interface AuthorizationTestMode {\n\tcimd?: CimdTestMode;\n\tauthCodeTtlMs?: number;\n\t/** Replace the pairing methods (a stub method proves the server needs no codes). */\n\tpairingMethods?: Partial<Record<PairingKind, PairingMethod>>;\n}\n\ninterface AuthorizationRequest {\n\tclient: ClientMetadata;\n\tredirectUri: string;\n\tstate: string | undefined;\n\tcodeChallenge: string;\n\taddressId: string;\n\tresource: string;\n\tscopes: string[];\n}\n\ninterface Pending extends AuthorizationRequest {\n\tid: string;\n\texpiresAt: number;\n\t/** The IP (prefix) key that opened it, for the per-IP cap. */\n\tip: string;\n}\n\ninterface IssuedCode extends AuthorizationRequest {\n\texpiresAt: number;\n\tused: boolean;\n\tgrantId?: string;\n}\n\nclass OAuthError extends Error {\n\treadonly status: number;\n\treadonly code: string;\n\tconstructor(status: number, code: string, description: string) {\n\t\tsuper(description);\n\t\tthis.status = status;\n\t\tthis.code = code;\n\t}\n}\n\nfunction constantTimeEqual(a: string, b: string): boolean {\n\tconst x = Buffer.from(a);\n\tconst y = Buffer.from(b);\n\treturn x.length === y.length && timingSafeEqual(x, y);\n}\n\n/** BASE64URL(SHA256(verifier)) (RFC 7636 §4.6). */\nexport function s256(verifier: string): string {\n\treturn new Bun.CryptoHasher(\"sha256\")\n\t\t.update(verifier)\n\t\t.digest()\n\t\t.toBase64({ alphabet: \"base64url\", omitPadding: true });\n}\n\n/** RFC 7636 §4.1: 43-128 unreserved characters. */\nconst VERIFIER = /^[A-Za-z0-9\\-._~]{43,128}$/;\n\n/** Parameters, refusing duplicates (RFC 6749 §3.1, §3.2). */\nfunction single(\n\tparams: URLSearchParams,\n\tnames: readonly string[],\n): Record<string, string | undefined> | { duplicate: string } {\n\tconst out: Record<string, string | undefined> = {};\n\tfor (const name of names) {\n\t\tconst values = params.getAll(name);\n\t\tif (values.length > 1) return { duplicate: name };\n\t\tconst value = values[0];\n\t\tout[name] = value === undefined || value === \"\" ? undefined : value;\n\t}\n\treturn out;\n}\n\nfunction random(bytes: number): string {\n\treturn crypto\n\t\t.getRandomValues(new Uint8Array(bytes))\n\t\t.toBase64({ alphabet: \"base64url\", omitPadding: true });\n}\n\n/** The origin a redirect URI sends the browser to, for CSP `form-action`. */\nfunction formTarget(redirectUri: string): string {\n\ttry {\n\t\tconst u = new URL(redirectUri);\n\t\treturn u.protocol === \"http:\" || u.protocol === \"https:\"\n\t\t\t? u.origin\n\t\t\t: u.protocol;\n\t} catch {\n\t\treturn \"'none'\";\n\t}\n}\n\nfunction hostOf(url: string): string {\n\ttry {\n\t\tconst u = new URL(url);\n\t\treturn u.host || u.protocol;\n\t} catch {\n\t\treturn url;\n\t}\n}\n\n/** The OAuth endpoints and pages, mounted by the relay. */\nexport class AuthorizationServer {\n\treadonly #host: AuthorizationHost;\n\treadonly #cimd: ClientMetadataFetcher;\n\t/** Insertion order is expiry order (one lifetime for all), so sweeps stop early. */\n\treadonly #pending = new Map<string, Pending>();\n\treadonly #pendingPerIp = new Map<string, number>();\n\treadonly #pendingPerAddress = new Map<string, number>();\n\treadonly #codes = new Map<string, IssuedCode>();\n\treadonly #authCodeTtlMs: number;\n\treadonly #methods: Partial<Record<PairingKind, PairingMethod>>;\n\treadonly #csrfSecret = random(32);\n\t/** `/authorize` page loads per IP. */\n\treadonly #viewsPerIp = new RateLimiter({\n\t\tcapacity: 30,\n\t\trefillPerSecond: 0.5,\n\t});\n\t/** Form posts per IP (every action; locks out only that network). */\n\treadonly #attemptsPerIp = new RateLimiter({\n\t\tcapacity: 20,\n\t\trefillPerSecond: 0.1,\n\t});\n\t/**\n\t * Code guesses (well-formed, against an active code) per address and IP:\n\t * one network cannot use up an address's allowance alone (DEC-061).\n\t */\n\treadonly #guessesPerAddressIp = new RateLimiter({\n\t\tcapacity: 10,\n\t\trefillPerSecond: 1 / 60,\n\t});\n\t/** Code guesses per address from everywhere: the brute-force cap (A1). */\n\treadonly #guessesPerAddress = new RateLimiter({\n\t\tcapacity: 30,\n\t\trefillPerSecond: 1 / 30,\n\t});\n\treadonly #tokenPerIp = new RateLimiter({ capacity: 30, refillPerSecond: 1 });\n\n\tconstructor(host: AuthorizationHost, testMode?: AuthorizationTestMode) {\n\t\tthis.#host = host;\n\t\tthis.#authCodeTtlMs = testMode?.authCodeTtlMs ?? AUTH_CODE_TTL_MS;\n\t\tthis.#methods = testMode?.pairingMethods ?? PAIRING_METHODS;\n\t\tthis.#cimd = new ClientMetadataFetcher({\n\t\t\tallowedHosts: host.config.clientIdHosts,\n\t\t\tlogger: host.logger,\n\t\t\t...(testMode?.cimd === undefined ? {} : { testMode: testMode.cimd }),\n\t\t});\n\t}\n\n\tget #issuer(): string {\n\t\treturn this.#host.publicUrl();\n\t}\n\n\t#cors(): Record<string, string> {\n\t\treturn this.#host.config.cors ? { \"access-control-allow-origin\": \"*\" } : {};\n\t}\n\n\t#json(\n\t\tstatus: number,\n\t\tvalue: unknown,\n\t\theaders: Record<string, string> = {},\n\t): Response {\n\t\treturn new Response(JSON.stringify(value), {\n\t\t\tstatus,\n\t\t\theaders: {\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t...this.#cors(),\n\t\t\t\t...headers,\n\t\t\t},\n\t\t});\n\t}\n\n\t/** CORS preflight for the metadata, token and revoke endpoints. */\n\tpreflight(methods: string): Response {\n\t\tif (!this.#host.config.cors) {\n\t\t\treturn new Response(null, { status: 405, headers: { allow: methods } });\n\t\t}\n\t\treturn new Response(null, {\n\t\t\tstatus: 204,\n\t\t\theaders: {\n\t\t\t\t...this.#cors(),\n\t\t\t\t\"access-control-allow-methods\": `${methods}, OPTIONS`,\n\t\t\t\t\"access-control-allow-headers\":\n\t\t\t\t\t\"authorization, content-type, mcp-protocol-version\",\n\t\t\t\t\"access-control-max-age\": \"600\",\n\t\t\t},\n\t\t});\n\t}\n\n\t// RFC 9728 and RFC 8414\n\n\t/** `/.well-known/oauth-protected-resource/a/{id}/mcp`. */\n\tprotectedResource(addressId: string): Response {\n\t\tif (!isAddressId(addressId))\n\t\t\treturn new Response(\"Not found\", { status: 404 });\n\t\treturn this.#json(\n\t\t\t200,\n\t\t\t{\n\t\t\t\tresource: `${this.#issuer}/a/${addressId}/mcp`,\n\t\t\t\tauthorization_servers: [this.#issuer],\n\t\t\t\tscopes_supported: [SCOPE],\n\t\t\t\tbearer_methods_supported: [\"header\"],\n\t\t\t\tresource_name: \"Tools of a web page (tab-mcp)\",\n\t\t\t},\n\t\t\t{ \"cache-control\": \"public, max-age=3600\" },\n\t\t);\n\t}\n\n\t/** `/.well-known/oauth-authorization-server`. */\n\tmetadata(): Response {\n\t\tconst issuer = this.#issuer;\n\t\treturn this.#json(\n\t\t\t200,\n\t\t\t{\n\t\t\t\tissuer,\n\t\t\t\tauthorization_endpoint: `${issuer}/authorize`,\n\t\t\t\ttoken_endpoint: `${issuer}/token`,\n\t\t\t\trevocation_endpoint: `${issuer}/revoke`,\n\t\t\t\tresponse_types_supported: [\"code\"],\n\t\t\t\tresponse_modes_supported: [\"query\"],\n\t\t\t\tgrant_types_supported: [\"authorization_code\", \"refresh_token\"],\n\t\t\t\tcode_challenge_methods_supported: [\"S256\"],\n\t\t\t\ttoken_endpoint_auth_methods_supported: [\"none\"],\n\t\t\t\trevocation_endpoint_auth_methods_supported: [\"none\"],\n\t\t\t\tscopes_supported: [SCOPE],\n\t\t\t\tclient_id_metadata_document_supported: true,\n\t\t\t\tauthorization_response_iss_parameter_supported: true,\n\t\t\t\tservice_documentation: \"https://github.com/ractive/tab-mcp\",\n\t\t\t},\n\t\t\t{ \"cache-control\": \"public, max-age=3600\" },\n\t\t);\n\t}\n\n\tstylesheet(): Response {\n\t\treturn new Response(AUTHORIZE_CSS, {\n\t\t\theaders: {\n\t\t\t\t\"content-type\": \"text/css; charset=utf-8\",\n\t\t\t\t\"cache-control\": \"public, max-age=3600\",\n\t\t\t\t\"x-content-type-options\": \"nosniff\",\n\t\t\t},\n\t\t});\n\t}\n\n\t// /authorize\n\n\t#page(\n\t\tstatus: number,\n\t\ttitle: string,\n\t\tbody: string,\n\t\tformTargets: readonly string[] = [],\n\t\textraHeaders: Record<string, string> = {},\n\t): Response {\n\t\tconst headers = pageHeaders(formTargets);\n\t\tfor (const [k, v] of Object.entries(extraHeaders)) headers.append(k, v);\n\t\treturn new Response(renderPage(title, body), { status, headers });\n\t}\n\n\t/** An error shown on the page: the redirect URI is not trusted (yet). */\n\t#errorPage(status: number, message: string): Response {\n\t\treturn this.#page(\n\t\t\tstatus,\n\t\t\t\"This connection cannot be made\",\n\t\t\t`<h1>This connection cannot be made</h1>\n<p role=\"alert\">${escapeHtml(message)}</p>\n<p>Go back to your AI tool and try again. If it keeps happening, the AI tool may not work with this relay.</p>`,\n\t\t);\n\t}\n\n\t/** The client's redirect URI with `error` (RFC 6749 §4.1.2.1) and `iss`. */\n\t#errorUrl(\n\t\tredirectUri: string,\n\t\tstate: string | undefined,\n\t\terror: string,\n\t\tdescription: string,\n\t): string {\n\t\tconst url = new URL(redirectUri);\n\t\tconst params: Record<string, string> = {\n\t\t\terror,\n\t\t\terror_description: description,\n\t\t\t...(state === undefined ? {} : { state }),\n\t\t\tiss: this.#issuer,\n\t\t};\n\t\tfor (const [k, v] of Object.entries(params)) url.searchParams.append(k, v);\n\t\treturn url.href;\n\t}\n\n\t/**\n\t * An invalid request from a client: not redirected automatically, so the\n\t * relay is no open redirector for self-published clients (RFC 9700\n\t * §4.11.2). The page names the destination and links to it (DEC-064).\n\t */\n\t#invalidRequestPage(\n\t\tredirectUri: string,\n\t\tstate: string | undefined,\n\t\terror: string,\n\t\tdescription: string,\n\t): Response {\n\t\tconst url = this.#errorUrl(redirectUri, state, error, description);\n\t\tconst host = hostOf(redirectUri);\n\t\treturn this.#page(\n\t\t\t400,\n\t\t\t\"This connection cannot be made\",\n\t\t\t`<h1>This connection cannot be made</h1>\n<p role=\"alert\">The AI tool sent a request this relay cannot accept: ${escapeHtml(description)} (${escapeHtml(error)}).</p>\n<p>You can go back to the AI tool at ${escapeHtml(host)} to tell it, or close this page.</p>\n<div class=\"actions\"><a class=\"button\" href=\"${escapeHtml(url)}\">Go back to ${escapeHtml(host)}</a></div>`,\n\t\t);\n\t}\n\n\t/** The user's own Cancel: back to the client at once (`access_denied`). */\n\t#redirectError(\n\t\tredirectUri: string,\n\t\tstate: string | undefined,\n\t\terror: string,\n\t\tdescription: string,\n\t): Response {\n\t\treturn new Response(null, {\n\t\t\tstatus: 303,\n\t\t\theaders: {\n\t\t\t\tlocation: this.#errorUrl(redirectUri, state, error, description),\n\t\t\t\t\"cache-control\": \"no-store\",\n\t\t\t\t\"referrer-policy\": \"no-referrer\",\n\t\t\t},\n\t\t});\n\t}\n\n\t#redirect(redirectUri: string, params: Record<string, string>): Response {\n\t\tconst url = new URL(redirectUri);\n\t\tfor (const [k, v] of Object.entries(params)) url.searchParams.append(k, v);\n\t\treturn new Response(null, {\n\t\t\tstatus: 303,\n\t\t\theaders: {\n\t\t\t\tlocation: url.href,\n\t\t\t\t\"cache-control\": \"no-store\",\n\t\t\t\t\"referrer-policy\": \"no-referrer\",\n\t\t\t},\n\t\t});\n\t}\n\n\t/** GET `/authorize`: check the request, then show the pairing page. */\n\tasync authorize(req: Request, ip: string): Promise<Response> {\n\t\tif (!this.#viewsPerIp.take(ip)) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t429,\n\t\t\t\t\"Too many requests from your network. Wait a minute and try again.\",\n\t\t\t);\n\t\t}\n\t\tconst query = new URL(req.url).searchParams;\n\t\tconst p = single(query, [\n\t\t\t\"response_type\",\n\t\t\t\"client_id\",\n\t\t\t\"redirect_uri\",\n\t\t\t\"code_challenge\",\n\t\t\t\"code_challenge_method\",\n\t\t\t\"state\",\n\t\t\t\"resource\",\n\t\t\t\"scope\",\n\t\t]);\n\t\tif (\"duplicate\" in p) {\n\t\t\tif (p.duplicate === \"client_id\" || p.duplicate === \"redirect_uri\") {\n\t\t\t\treturn this.#errorPage(400, `The request names ${p.duplicate} twice.`);\n\t\t\t}\n\t\t}\n\t\tconst clientId = \"duplicate\" in p ? query.get(\"client_id\") : p[\"client_id\"];\n\t\tconst redirectUri =\n\t\t\t\"duplicate\" in p ? query.get(\"redirect_uri\") : p[\"redirect_uri\"];\n\t\tif (clientId === undefined || clientId === null) {\n\t\t\treturn this.#errorPage(400, \"The request has no client_id.\");\n\t\t}\n\t\tlet client: ClientMetadata;\n\t\ttry {\n\t\t\tclient = await this.#cimd.get(clientId);\n\t\t} catch (error) {\n\t\t\tif (error instanceof ClientMetadataError) {\n\t\t\t\tthis.#host.logger.info(\"oauth.client_refused\", {\n\t\t\t\t\treason: error.reason,\n\t\t\t\t\thost: hostOf(clientId).slice(0, 100),\n\t\t\t\t});\n\t\t\t\treturn this.#errorPage(400, error.message);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tif (redirectUri === undefined || redirectUri === null) {\n\t\t\treturn this.#errorPage(400, \"The request has no redirect_uri.\");\n\t\t}\n\t\tif (!client.redirectUris.some((r) => redirectUriMatches(redirectUri, r))) {\n\t\t\tthis.#host.logger.info(\"oauth.client_refused\", {\n\t\t\t\treason: \"redirect_uri\",\n\t\t\t\thost: client.host,\n\t\t\t});\n\t\t\treturn this.#errorPage(\n\t\t\t\t400,\n\t\t\t\t`${client.name} asked to return to an address it has not registered (${hostOf(redirectUri)}).`,\n\t\t\t);\n\t\t}\n\t\t// From here on errors go back to the (now trusted) redirect URI.\n\t\tconst state = \"duplicate\" in p ? undefined : p[\"state\"];\n\t\tconst fail = (error: string, description: string) =>\n\t\t\tthis.#invalidRequestPage(redirectUri, state, error, description);\n\t\tif (\"duplicate\" in p) {\n\t\t\treturn fail(\"invalid_request\", `${p.duplicate} was sent more than once`);\n\t\t}\n\t\tif (state !== undefined && state.length > MAX_STATE_LENGTH) {\n\t\t\treturn fail(\"invalid_request\", \"state is too long\");\n\t\t}\n\t\tif (p[\"response_type\"] !== \"code\") {\n\t\t\treturn fail(\n\t\t\t\t\"unsupported_response_type\",\n\t\t\t\t\"only response_type=code is supported\",\n\t\t\t);\n\t\t}\n\t\tconst challenge = p[\"code_challenge\"];\n\t\tif (challenge === undefined) {\n\t\t\treturn fail(\"invalid_request\", \"code_challenge is required (PKCE)\");\n\t\t}\n\t\tif (p[\"code_challenge_method\"] !== \"S256\") {\n\t\t\treturn fail(\"invalid_request\", \"code_challenge_method must be S256\");\n\t\t}\n\t\tif (!/^[A-Za-z0-9\\-._~]{43,128}$/.test(challenge)) {\n\t\t\treturn fail(\"invalid_request\", \"code_challenge is malformed\");\n\t\t}\n\t\tconst resource = p[\"resource\"];\n\t\tconst addressId = this.#addressOf(resource);\n\t\tif (resource === undefined || addressId === undefined) {\n\t\t\treturn fail(\n\t\t\t\t\"invalid_target\",\n\t\t\t\t\"resource must be the MCP address of a page on this relay\",\n\t\t\t);\n\t\t}\n\t\tconst scopes = this.#grantedScopes(p[\"scope\"]);\n\t\tif (scopes === undefined) {\n\t\t\treturn fail(\"invalid_scope\", `the only scope is \"${SCOPE}\"`);\n\t\t}\n\n\t\t// No connected tab: nothing to pair with, so nothing is kept (DEC-061).\n\t\tif (this.#host.session(addressId) === undefined) {\n\t\t\treturn this.#offlinePage(\n\t\t\t\tclient,\n\t\t\t\t`/authorize${new URL(req.url).search}`,\n\t\t\t\tthis.#errorUrl(\n\t\t\t\t\tredirectUri,\n\t\t\t\t\tstate,\n\t\t\t\t\t\"access_denied\",\n\t\t\t\t\t\"the user cancelled the connection\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tthis.#sweepPending();\n\t\tif (\n\t\t\tthis.#pending.size >= MAX_PENDING ||\n\t\t\t(this.#pendingPerIp.get(ip) ?? 0) >= MAX_PENDING_PER_IP ||\n\t\t\t(this.#pendingPerAddress.get(addressId) ?? 0) >= MAX_PENDING_PER_ADDRESS\n\t\t) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t429,\n\t\t\t\t\"Too many connection requests are open right now. Wait a few minutes and try again.\",\n\t\t\t);\n\t\t}\n\t\tconst pending: Pending = {\n\t\t\tid: random(24),\n\t\t\texpiresAt: Date.now() + PENDING_TTL_MS,\n\t\t\tip,\n\t\t\tclient,\n\t\t\tredirectUri,\n\t\t\tstate,\n\t\t\tcodeChallenge: challenge,\n\t\t\taddressId,\n\t\t\tresource,\n\t\t\tscopes,\n\t\t};\n\t\tthis.#addPending(pending);\n\t\tconst browser = this.#browserId(req);\n\t\treturn this.#pairingPage(\n\t\t\tpending,\n\t\t\tbrowser.id,\n\t\t\tundefined,\n\t\t\t200,\n\t\t\tbrowser.cookie,\n\t\t);\n\t}\n\n\t#addPending(p: Pending): void {\n\t\tthis.#pending.set(p.id, p);\n\t\tthis.#pendingPerIp.set(p.ip, (this.#pendingPerIp.get(p.ip) ?? 0) + 1);\n\t\tthis.#pendingPerAddress.set(\n\t\t\tp.addressId,\n\t\t\t(this.#pendingPerAddress.get(p.addressId) ?? 0) + 1,\n\t\t);\n\t}\n\n\t#dropPending(p: Pending): void {\n\t\tif (!this.#pending.delete(p.id)) return;\n\t\tconst dec = (map: Map<string, number>, key: string) => {\n\t\t\tconst n = (map.get(key) ?? 1) - 1;\n\t\t\tif (n <= 0) map.delete(key);\n\t\t\telse map.set(key, n);\n\t\t};\n\t\tdec(this.#pendingPerIp, p.ip);\n\t\tdec(this.#pendingPerAddress, p.addressId);\n\t}\n\n\t/** The tab is not connected: try again by loading the page again. */\n\t#offlinePage(\n\t\tclient: ClientMetadata,\n\t\tretryUrl: string,\n\t\tcancelUrl: string,\n\t\terror?: string,\n\t): Response {\n\t\tconst errorHtml =\n\t\t\terror === undefined\n\t\t\t\t? \"\"\n\t\t\t\t: `<p class=\"error\" role=\"alert\">${escapeHtml(error)}</p>`;\n\t\tconst body = `<h1>Open the page first</h1>\n${errorHtml}\n<p><strong>${escapeHtml(client.name)}</strong> (${escapeHtml(client.host)}) wants to use the tools of a web page, but that page is not open right now.</p>\n<p>Open the page, click “Connect your AI tool”, then try again here.</p>\n<div class=\"actions\">\n<a class=\"button primary\" href=\"${escapeHtml(retryUrl)}\">Try again</a>\n<a class=\"button\" href=\"${escapeHtml(cancelUrl)}\">Cancel</a>\n</div>`;\n\t\treturn this.#page(200, \"Open the page first\", body);\n\t}\n\n\t/** POST `/authorize`: the pairing form (connect, cancel, try again). */\n\tasync authorizeSubmit(req: Request, ip: string): Promise<Response> {\n\t\t// Only our own form may post here (defence in depth beside the token).\n\t\tconst origin = req.headers.get(\"origin\");\n\t\tconst site = req.headers.get(\"sec-fetch-site\");\n\t\tif (\n\t\t\t(origin !== null && origin !== this.#issuer) ||\n\t\t\t(site !== null && site !== \"same-origin\")\n\t\t) {\n\t\t\treturn this.#errorPage(403, \"This form can only be sent from this page.\");\n\t\t}\n\t\tif (!this.#attemptsPerIp.take(ip)) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t429,\n\t\t\t\t\"Too many attempts from your network. Wait a few minutes, then start again from your AI tool.\",\n\t\t\t);\n\t\t}\n\t\tconst type = (req.headers.get(\"content-type\") ?? \"\").split(\";\")[0]?.trim();\n\t\tif (type !== \"application/x-www-form-urlencoded\") {\n\t\t\treturn this.#errorPage(400, \"The form was not sent correctly.\");\n\t\t}\n\t\tconst text = await this.#readForm(req);\n\t\tif (text === undefined) {\n\t\t\treturn this.#errorPage(413, \"The form was too large.\");\n\t\t}\n\t\tconst form = new URLSearchParams(text);\n\t\tconst pending = this.#pending.get(form.get(\"request_id\") ?? \"\");\n\t\tif (pending === undefined || pending.expiresAt <= Date.now()) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t400,\n\t\t\t\t\"This connection request has expired or was already used.\",\n\t\t\t);\n\t\t}\n\t\tconst browser = this.#browserId(req);\n\t\tconst csrf = form.get(\"csrf\") ?? \"\";\n\t\tif (\n\t\t\tbrowser.cookie !== undefined ||\n\t\t\t!Bun.CSRF.verify(csrf, {\n\t\t\t\tsecret: this.#csrfSecret,\n\t\t\t\tsessionId: `${pending.id}.${browser.id}`,\n\t\t\t\tmaxAge: PENDING_TTL_MS,\n\t\t\t})\n\t\t) {\n\t\t\t// A new cookie means the browser did not send ours: not the same visit.\n\t\t\treturn this.#errorPage(\n\t\t\t\t403,\n\t\t\t\t\"The form could not be checked. Your browser may block cookies for this site.\",\n\t\t\t);\n\t\t}\n\n\t\tconst action = form.get(\"action\");\n\t\tif (action === \"cancel\") {\n\t\t\tthis.#dropPending(pending);\n\t\t\tthis.#host.logger.info(\"oauth.cancelled\", {\n\t\t\t\taddress: shortAddress(pending.addressId),\n\t\t\t\tclient: pending.client.host,\n\t\t\t});\n\t\t\treturn this.#redirectError(\n\t\t\t\tpending.redirectUri,\n\t\t\t\tpending.state,\n\t\t\t\t\"access_denied\",\n\t\t\t\t\"the user cancelled the connection\",\n\t\t\t);\n\t\t}\n\t\tif (action !== \"connect\") {\n\t\t\treturn this.#pairingPage(pending, browser.id);\n\t\t}\n\n\t\tconst session = this.#host.session(pending.addressId);\n\t\tif (session === undefined) {\n\t\t\treturn this.#pairingPage(\n\t\t\t\tpending,\n\t\t\t\tbrowser.id,\n\t\t\t\t\"The page is still not open.\",\n\t\t\t);\n\t\t}\n\t\tconst method = this.#methods[session.site.pairing];\n\t\tif (method === undefined) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t500,\n\t\t\t\t\"This page's pairing method is not available.\",\n\t\t\t);\n\t\t}\n\t\t// Only a real guess is charged: the method calls this right before it\n\t\t// compares a well-formed answer (DEC-061).\n\t\tconst admit = () =>\n\t\t\tthis.#guessesPerAddressIp.take(`${pending.addressId}|${ip}`) &&\n\t\t\tthis.#guessesPerAddress.take(pending.addressId);\n\t\tconst result = await method.check(session, form, admit);\n\t\tif (!result.ok) {\n\t\t\tthis.#host.logger.info(\"oauth.pairing_failed\", {\n\t\t\t\taddress: shortAddress(pending.addressId),\n\t\t\t\tclient: pending.client.host,\n\t\t\t\treason: result.reason,\n\t\t\t});\n\t\t\treturn this.#pairingPage(\n\t\t\t\tpending,\n\t\t\t\tbrowser.id,\n\t\t\t\tresult.message,\n\t\t\t\tresult.reason === \"rate_limited\" ? 429 : 400,\n\t\t\t);\n\t\t}\n\n\t\tthis.#dropPending(pending);\n\t\tconst code = random(32);\n\t\tif (this.#codes.size >= MAX_CODES) this.#sweepCodes(true);\n\t\tconst { id: _id, expiresAt: _expires, ip: _ip, ...request } = pending;\n\t\tthis.#codes.set(hashToken(code), {\n\t\t\t...request,\n\t\t\texpiresAt: Date.now() + this.#authCodeTtlMs,\n\t\t\tused: false,\n\t\t});\n\t\tthis.#host.logger.info(\"oauth.paired\", {\n\t\t\taddress: shortAddress(pending.addressId),\n\t\t\tclient: pending.client.host,\n\t\t\tmethod: method.kind,\n\t\t});\n\t\treturn this.#redirect(pending.redirectUri, {\n\t\t\tcode,\n\t\t\t...(pending.state === undefined ? {} : { state: pending.state }),\n\t\t\tiss: this.#issuer,\n\t\t});\n\t}\n\n\t#addressOf(resource: string | undefined): string | undefined {\n\t\tif (resource === undefined) return undefined;\n\t\tconst prefix = `${this.#issuer}/a/`;\n\t\tif (!resource.startsWith(prefix) || !resource.endsWith(\"/mcp\")) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst id = resource.slice(prefix.length, -\"/mcp\".length);\n\t\treturn isAddressId(id) ? id : undefined;\n\t}\n\n\t/** Requested scopes reduced to what exists; `undefined` = none of them. */\n\t#grantedScopes(scope: string | undefined): string[] | undefined {\n\t\tif (scope === undefined) return [SCOPE];\n\t\tconst requested = scope.split(\" \").filter((s) => s !== \"\");\n\t\tif (requested.length === 0) return [SCOPE];\n\t\treturn requested.includes(SCOPE) ? [SCOPE] : undefined;\n\t}\n\n\t/** The browser's visit id from our cookie, or a new one with its cookie. */\n\t#browserId(req: Request): { id: string; cookie?: string } {\n\t\tconst name = this.#cookieName();\n\t\tconst header = req.headers.get(\"cookie\") ?? \"\";\n\t\tfor (const part of header.split(\";\")) {\n\t\t\tconst [k, v] = part.trim().split(\"=\");\n\t\t\tif (k === name && v !== undefined && /^[A-Za-z0-9_-]{22}$/.test(v)) {\n\t\t\t\treturn { id: v };\n\t\t\t}\n\t\t}\n\t\tconst id = random(16);\n\t\tconst secure = this.#issuer.startsWith(\"https:\") ? \"; Secure\" : \"\";\n\t\treturn {\n\t\t\tid,\n\t\t\tcookie: `${name}=${id}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${PENDING_TTL_MS / 1000}${secure}`,\n\t\t};\n\t}\n\n\t#cookieName(): string {\n\t\treturn this.#issuer.startsWith(\"https:\")\n\t\t\t? \"__Host-tab-mcp-authorize\"\n\t\t\t: \"tab-mcp-authorize\";\n\t}\n\n\tasync #readForm(req: Request): Promise<string | undefined> {\n\t\tconst length = Number(req.headers.get(\"content-length\") ?? \"0\");\n\t\tif (length > MAX_FORM_BYTES) return undefined;\n\t\tconst bytes = await req.arrayBuffer().catch(() => new ArrayBuffer(0));\n\t\tif (bytes.byteLength > MAX_FORM_BYTES) return undefined;\n\t\treturn new TextDecoder().decode(bytes);\n\t}\n\n\t#pairingPage(\n\t\tpending: Pending,\n\t\tbrowserId: string,\n\t\terror?: string,\n\t\tstatus = 200,\n\t\tcookie?: string,\n\t): Response {\n\t\tconst csrf = Bun.CSRF.generate(this.#csrfSecret, {\n\t\t\tsessionId: `${pending.id}.${browserId}`,\n\t\t\texpiresIn: PENDING_TTL_MS,\n\t\t});\n\t\tconst client = pending.client;\n\t\tconst clientLabel = `<strong>${escapeHtml(client.name)}</strong> (${escapeHtml(client.host)})`;\n\t\tconst hidden = `<input type=\"hidden\" name=\"request_id\" value=\"${escapeHtml(pending.id)}\">\n<input type=\"hidden\" name=\"csrf\" value=\"${escapeHtml(csrf)}\">`;\n\t\tconst errorHtml =\n\t\t\terror === undefined\n\t\t\t\t? \"\"\n\t\t\t\t: `<p class=\"error\" role=\"alert\" id=\"error\">${escapeHtml(error)}</p>`;\n\t\tconst extra = cookie === undefined ? {} : { \"set-cookie\": cookie };\n\t\tconst targets = [formTarget(pending.redirectUri)];\n\t\tconst cancel = `<button type=\"submit\" class=\"secondary\" name=\"action\" value=\"cancel\" formnovalidate>Cancel</button>`;\n\n\t\tconst session = this.#host.session(pending.addressId);\n\t\tif (session === undefined) {\n\t\t\t// The tab went away after the page was opened: keep the request,\n\t\t\t// so Try again (a post) can continue once the tab is back.\n\t\t\tconst body = `<h1>Open the page first</h1>\n${errorHtml}\n<p>${clientLabel} wants to use the tools of a web page, but that page is not open right now.</p>\n<p>Open the page, click “Connect your AI tool”, then try again here.</p>\n<form method=\"post\" action=\"/authorize\">\n${hidden}\n<div class=\"actions\">\n<button type=\"submit\" class=\"primary\" name=\"action\" value=\"retry\">Try again</button>\n${cancel}\n</div>\n</form>`;\n\t\t\treturn this.#page(status, \"Open the page first\", body, targets, extra);\n\t\t}\n\n\t\tconst method = this.#methods[session.site.pairing];\n\t\tif (method === undefined) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t500,\n\t\t\t\t\"This page's pairing method is not available.\",\n\t\t\t);\n\t\t}\n\t\t// A browser always sends an Origin; only a non-browser tab on an open\n\t\t// relay has none.\n\t\tconst page =\n\t\t\tsession.origin === \"\"\n\t\t\t\t? \"a page that did not say where it runs\"\n\t\t\t\t: `<span class=\"origin\">${escapeHtml(session.origin)}</span>`;\n\t\tconst target =\n\t\t\tsession.appName === undefined\n\t\t\t\t? `tools from ${page}`\n\t\t\t\t: `<strong>${escapeHtml(session.appName)}</strong> on ${page}`;\n\t\t// The verified host is part of the heading and title, so a\n\t\t// self-declared name never stands alone (DEC-065).\n\t\tconst heading = `Connect ${client.name} from ${client.host}`;\n\t\tconst body = `<h1>${escapeHtml(heading)}</h1>\n<p>You're connecting ${clientLabel} to ${target}.</p>\n<p>${escapeHtml(client.name)} can then use this page's tools while the page is open. You can disconnect it in the page at any time.</p>\n${errorHtml}\n<form method=\"post\" action=\"/authorize\">\n${hidden}\n${method.render(session)}\n<div class=\"actions\">\n<button type=\"submit\" class=\"primary\" name=\"action\" value=\"connect\">Connect</button>\n${cancel}\n</div>\n</form>\n<p class=\"help\">After you connect, your browser goes back to ${escapeHtml(hostOf(pending.redirectUri))}. Only connect AI tools you started yourself.</p>`;\n\t\treturn this.#page(status, heading, body, targets, extra);\n\t}\n\n\t// /token\n\n\t/** POST `/token`. */\n\tasync token(req: Request, ip: string): Promise<Response> {\n\t\tconst noStore = { \"cache-control\": \"no-store\", pragma: \"no-cache\" };\n\t\ttry {\n\t\t\tif (!this.#tokenPerIp.take(ip)) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t429,\n\t\t\t\t\t\"temporarily_unavailable\",\n\t\t\t\t\t\"too many requests; try again shortly\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst params = await this.#formParams(req);\n\t\t\tconst p = single(params, [\n\t\t\t\t\"grant_type\",\n\t\t\t\t\"client_id\",\n\t\t\t\t\"code\",\n\t\t\t\t\"redirect_uri\",\n\t\t\t\t\"code_verifier\",\n\t\t\t\t\"refresh_token\",\n\t\t\t\t\"resource\",\n\t\t\t\t\"scope\",\n\t\t\t]);\n\t\t\tif (\"duplicate\" in p) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t400,\n\t\t\t\t\t\"invalid_request\",\n\t\t\t\t\t`${p.duplicate} was sent more than once`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst clientId = p[\"client_id\"];\n\t\t\tif (clientId === undefined) {\n\t\t\t\tthrow new OAuthError(400, \"invalid_request\", \"client_id is required\");\n\t\t\t}\n\t\t\tlet body: Record<string, unknown>;\n\t\t\tif (p[\"grant_type\"] === \"authorization_code\") {\n\t\t\t\tbody = await this.#codeGrant(p, clientId);\n\t\t\t} else if (p[\"grant_type\"] === \"refresh_token\") {\n\t\t\t\tbody = await this.#refreshGrant(p, clientId);\n\t\t\t} else if (p[\"grant_type\"] === undefined) {\n\t\t\t\tthrow new OAuthError(400, \"invalid_request\", \"grant_type is required\");\n\t\t\t} else {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t400,\n\t\t\t\t\t\"unsupported_grant_type\",\n\t\t\t\t\t\"only authorization_code and refresh_token are supported\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn this.#json(200, body, noStore);\n\t\t} catch (error) {\n\t\t\treturn this.#oauthErrorResponse(error, noStore);\n\t\t}\n\t}\n\n\t#oauthErrorResponse(\n\t\terror: unknown,\n\t\theaders: Record<string, string>,\n\t): Response {\n\t\tif (error instanceof OAuthError) {\n\t\t\tconst extra: Record<string, string> = { ...headers };\n\t\t\tif (error.status === 401)\n\t\t\t\textra[\"www-authenticate\"] = 'Basic realm=\"tab-mcp\"';\n\t\t\tif (error.status === 429 || error.status === 503)\n\t\t\t\textra[\"retry-after\"] = \"10\";\n\t\t\treturn this.#json(\n\t\t\t\terror.status,\n\t\t\t\t{ error: error.code, error_description: error.message },\n\t\t\t\textra,\n\t\t\t);\n\t\t}\n\t\tthis.#host.logger.error(\"oauth.error\", {\n\t\t\tmessage: error instanceof Error ? error.name : \"unknown\",\n\t\t});\n\t\treturn this.#json(\n\t\t\t503,\n\t\t\t{\n\t\t\t\terror: \"temporarily_unavailable\",\n\t\t\t\terror_description: \"the relay cannot issue tokens right now\",\n\t\t\t},\n\t\t\t{ ...headers, \"retry-after\": \"10\" },\n\t\t);\n\t}\n\n\t/** Form parameters of a token or revocation request (client auth `none` only). */\n\tasync #formParams(req: Request): Promise<URLSearchParams> {\n\t\tconst type = (req.headers.get(\"content-type\") ?? \"\").split(\";\")[0]?.trim();\n\t\tif (type !== \"application/x-www-form-urlencoded\") {\n\t\t\tthrow new OAuthError(\n\t\t\t\t400,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"the body must be application/x-www-form-urlencoded\",\n\t\t\t);\n\t\t}\n\t\tif (req.headers.get(\"authorization\") !== null) {\n\t\t\t// RFC 6749 §5.2: a client that tried to authenticate gets 401.\n\t\t\tthrow new OAuthError(\n\t\t\t\t401,\n\t\t\t\t\"invalid_client\",\n\t\t\t\t\"client authentication is not supported (token_endpoint_auth_method none)\",\n\t\t\t);\n\t\t}\n\t\tconst text = await this.#readForm(req);\n\t\tif (text === undefined) {\n\t\t\tthrow new OAuthError(413, \"invalid_request\", \"the request is too large\");\n\t\t}\n\t\tconst params = new URLSearchParams(text);\n\t\tif (params.has(\"client_secret\") || params.has(\"client_assertion\")) {\n\t\t\tthrow new OAuthError(\n\t\t\t\t400,\n\t\t\t\t\"invalid_client\",\n\t\t\t\t\"client authentication is not supported (token_endpoint_auth_method none)\",\n\t\t\t);\n\t\t}\n\t\treturn params;\n\t}\n\n\tasync #codeGrant(\n\t\tp: Record<string, string | undefined>,\n\t\tclientId: string,\n\t): Promise<Record<string, unknown>> {\n\t\tconst code = p[\"code\"];\n\t\tconst redirectUri = p[\"redirect_uri\"];\n\t\tconst verifier = p[\"code_verifier\"];\n\t\tif (\n\t\t\tcode === undefined ||\n\t\t\tredirectUri === undefined ||\n\t\t\tverifier === undefined\n\t\t) {\n\t\t\tthrow new OAuthError(\n\t\t\t\t400,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"code, redirect_uri and code_verifier are required\",\n\t\t\t);\n\t\t}\n\t\tconst key = hashToken(code);\n\t\tconst issued = this.#codes.get(key);\n\t\tconst invalid = (why: string) => new OAuthError(400, \"invalid_grant\", why);\n\t\tif (issued === undefined) throw invalid(\"the code is not valid\");\n\t\tif (issued.used) {\n\t\t\t// RFC 6749 §4.1.2: a code used twice revokes what it produced.\n\t\t\tif (issued.grantId !== undefined) {\n\t\t\t\tawait this.#revokeGrant(\n\t\t\t\t\tissued.addressId,\n\t\t\t\t\tissued.grantId,\n\t\t\t\t\t\"reuse_detected\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow invalid(\"the code was already used\");\n\t\t}\n\t\tissued.used = true; // a failed check below burns the code too\n\t\tif (issued.expiresAt <= Date.now()) throw invalid(\"the code has expired\");\n\t\tif (!constantTimeEqual(clientId, issued.client.clientId)) {\n\t\t\tthrow invalid(\"the code was issued to another client\");\n\t\t}\n\t\tif (redirectUri !== issued.redirectUri) {\n\t\t\tthrow invalid(\"redirect_uri does not match the authorization request\");\n\t\t}\n\t\tif (p[\"resource\"] !== undefined && p[\"resource\"] !== issued.resource) {\n\t\t\tthrow new OAuthError(\n\t\t\t\t400,\n\t\t\t\t\"invalid_target\",\n\t\t\t\t\"resource does not match the authorization request\",\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\t!VERIFIER.test(verifier) ||\n\t\t\t!constantTimeEqual(s256(verifier), issued.codeChallenge)\n\t\t) {\n\t\t\tthrow invalid(\"code_verifier does not match the code_challenge\");\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tconst grantId = newId(\"g\");\n\t\tissued.grantId = grantId;\n\t\tconst config = this.#host.config;\n\t\tconst tokens = await issueTokenPair(\n\t\t\tthis.#host.store,\n\t\t\t{\n\t\t\t\tgrantId,\n\t\t\t\taddressId: issued.addressId,\n\t\t\t\tclientId: issued.client.clientId,\n\t\t\t\tclientName: issued.client.name,\n\t\t\t\tscopes: issued.scopes,\n\t\t\t\tgrantCreatedAt: now,\n\t\t\t},\n\t\t\t{\n\t\t\t\taccessTtlMs: config.accessTokenTtlMs,\n\t\t\t\trefreshTtlMs: config.refreshTokenTtlMs,\n\t\t\t\tgrantEndsAt: now + config.grantLifetimeMs,\n\t\t\t\tnow,\n\t\t\t},\n\t\t);\n\t\tif (tokens === undefined) {\n\t\t\t// Revoked while the tokens were issued (code reuse, New address).\n\t\t\tthrow invalid(\"the connection was revoked\");\n\t\t}\n\t\tthis.#host.logger.info(\"oauth.grant_created\", {\n\t\t\taddress: shortAddress(issued.addressId),\n\t\t\tclient: issued.client.host,\n\t\t});\n\t\tthis.#host.grantAdded(issued.addressId, {\n\t\t\tgrantId,\n\t\t\tclient: {\n\t\t\t\tid: issued.client.clientId,\n\t\t\t\tname: issued.client.name,\n\t\t\t\thost: issued.client.host,\n\t\t\t},\n\t\t\tcreatedAt: new Date(now).toISOString(),\n\t\t});\n\t\treturn this.#tokenBody(tokens, issued.scopes);\n\t}\n\n\t#tokenBody(\n\t\ttokens: { accessToken: string; refreshToken: string; expiresIn: number },\n\t\tscopes: string[],\n\t): Record<string, unknown> {\n\t\treturn {\n\t\t\taccess_token: tokens.accessToken,\n\t\t\ttoken_type: \"Bearer\",\n\t\t\texpires_in: tokens.expiresIn,\n\t\t\trefresh_token: tokens.refreshToken,\n\t\t\tscope: scopes.join(\" \"),\n\t\t};\n\t}\n\n\tasync #refreshGrant(\n\t\tp: Record<string, string | undefined>,\n\t\tclientId: string,\n\t): Promise<Record<string, unknown>> {\n\t\tconst token = p[\"refresh_token\"];\n\t\tif (token === undefined) {\n\t\t\tthrow new OAuthError(400, \"invalid_request\", \"refresh_token is required\");\n\t\t}\n\t\tconst invalid = (why: string) => new OAuthError(400, \"invalid_grant\", why);\n\t\tconst hash = hashToken(token);\n\t\tconst record = await this.#host.store.get(hash);\n\t\tif (record === undefined || record.kind !== \"refresh\") {\n\t\t\tthrow invalid(\"the refresh token is not valid\");\n\t\t}\n\t\tif (!constantTimeEqual(clientId, record.clientId)) {\n\t\t\tthrow invalid(\"the refresh token was issued to another client\");\n\t\t}\n\t\tconst now = Date.now();\n\t\tif (record.expiresAt <= now) throw invalid(\"the refresh token has expired\");\n\t\tif (record.usedAt !== undefined) {\n\t\t\tawait this.#reuseDetected(record);\n\t\t\tthrow invalid(\n\t\t\t\t\"the refresh token was already used; the connection was revoked\",\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tp[\"resource\"] !== undefined &&\n\t\t\tp[\"resource\"] !== `${this.#issuer}/a/${record.addressId}/mcp`\n\t\t) {\n\t\t\tthrow new OAuthError(\n\t\t\t\t400,\n\t\t\t\t\"invalid_target\",\n\t\t\t\t\"resource is not the address this token belongs to\",\n\t\t\t);\n\t\t}\n\t\tconst scope = p[\"scope\"];\n\t\tif (scope !== undefined) {\n\t\t\tconst wanted = scope.split(\" \").filter((s) => s !== \"\");\n\t\t\tif (!wanted.every((s) => record.scopes.includes(s))) {\n\t\t\t\tthrow new OAuthError(400, \"invalid_scope\", \"scope exceeds the grant\");\n\t\t\t}\n\t\t}\n\t\t// Atomic: of two refreshes with the same token only one gets here.\n\t\tif (!(await this.#host.store.markUsed(hash, now))) {\n\t\t\tawait this.#reuseDetected(record);\n\t\t\tthrow invalid(\n\t\t\t\t\"the refresh token was already used; the connection was revoked\",\n\t\t\t);\n\t\t}\n\t\tconst tokens = await issueTokenPair(\n\t\t\tthis.#host.store,\n\t\t\t{\n\t\t\t\tgrantId: record.grantId,\n\t\t\t\taddressId: record.addressId,\n\t\t\t\tclientId: record.clientId,\n\t\t\t\tclientName: record.clientName,\n\t\t\t\tscopes: record.scopes,\n\t\t\t\tgrantCreatedAt: record.grantCreatedAt,\n\t\t\t},\n\t\t\t{\n\t\t\t\taccessTtlMs: this.#host.config.accessTokenTtlMs,\n\t\t\t\trefreshTtlMs: this.#host.config.refreshTokenTtlMs,\n\t\t\t\t// Refreshes slide, but never beyond the grant's absolute end (DEC-062).\n\t\t\t\tgrantEndsAt: record.grantCreatedAt + this.#host.config.grantLifetimeMs,\n\t\t\t\tnow,\n\t\t\t},\n\t\t);\n\t\tif (tokens === undefined) {\n\t\t\t// The grant was revoked while this refresh ran (DEC-063).\n\t\t\tthrow invalid(\"the connection was revoked\");\n\t\t}\n\t\tthis.#host.logger.debug(\"oauth.refreshed\", {\n\t\t\taddress: shortAddress(record.addressId),\n\t\t\tclient: hostOf(record.clientId),\n\t\t});\n\t\treturn this.#tokenBody(tokens, record.scopes);\n\t}\n\n\tasync #reuseDetected(record: TokenRecord): Promise<void> {\n\t\tthis.#host.logger.warn(\"oauth.refresh_reuse\", {\n\t\t\taddress: shortAddress(record.addressId),\n\t\t\tclient: hostOf(record.clientId),\n\t\t});\n\t\tawait this.#revokeGrant(record.addressId, record.grantId, \"reuse_detected\");\n\t}\n\n\tasync #revokeGrant(\n\t\taddressId: string,\n\t\tgrantId: string,\n\t\treason: string,\n\t): Promise<void> {\n\t\tconst now = Date.now();\n\t\tconst n = await this.#host.store.revoke(\n\t\t\t{ grantId },\n\t\t\t{ now, keepUntil: now + this.#host.config.grantLifetimeMs },\n\t\t);\n\t\tif (n > 0) this.#host.grantRemoved(addressId, grantId, reason);\n\t}\n\n\t// /revoke\n\n\t/** POST `/revoke` (RFC 7009). */\n\tasync revoke(req: Request, ip: string): Promise<Response> {\n\t\tconst noStore = { \"cache-control\": \"no-store\" };\n\t\ttry {\n\t\t\tif (!this.#tokenPerIp.take(ip)) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t429,\n\t\t\t\t\t\"temporarily_unavailable\",\n\t\t\t\t\t\"too many requests; try again shortly\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst params = await this.#formParams(req);\n\t\t\tconst p = single(params, [\"token\", \"client_id\", \"token_type_hint\"]);\n\t\t\tif (\"duplicate\" in p) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t400,\n\t\t\t\t\t\"invalid_request\",\n\t\t\t\t\t`${p.duplicate} was sent more than once`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst token = p[\"token\"];\n\t\t\tconst clientId = p[\"client_id\"];\n\t\t\tif (token === undefined || clientId === undefined) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t400,\n\t\t\t\t\t\"invalid_request\",\n\t\t\t\t\t\"token and client_id are required\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst record = await this.#host.store.get(hashToken(token));\n\t\t\t// RFC 7009 §2.2: an unknown token is not an error.\n\t\t\tif (record === undefined)\n\t\t\t\treturn new Response(null, {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\theaders: { ...this.#cors(), ...noStore },\n\t\t\t\t});\n\t\t\tif (!constantTimeEqual(clientId, record.clientId)) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t400,\n\t\t\t\t\t\"invalid_client\",\n\t\t\t\t\t\"the token was issued to another client\",\n\t\t\t\t);\n\t\t\t}\n\t\t\t// The grant is the connection: revoking either token ends it.\n\t\t\tawait this.#revokeGrant(record.addressId, record.grantId, \"revoked\");\n\t\t\tthis.#host.logger.info(\"oauth.revoked\", {\n\t\t\t\taddress: shortAddress(record.addressId),\n\t\t\t\tclient: hostOf(record.clientId),\n\t\t\t\tby: \"client\",\n\t\t\t});\n\t\t\treturn new Response(null, {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: { ...this.#cors(), ...noStore },\n\t\t\t});\n\t\t} catch (error) {\n\t\t\treturn this.#oauthErrorResponse(error, noStore);\n\t\t}\n\t}\n\n\t// Housekeeping\n\n\t/** Drop expired requests; insertion order is expiry order, so stop at the first live one. */\n\t#sweepPending(): void {\n\t\tconst now = Date.now();\n\t\tfor (const p of this.#pending.values()) {\n\t\t\tif (p.expiresAt > now) break;\n\t\t\tthis.#dropPending(p);\n\t\t}\n\t}\n\n\t#sweepCodes(force = false): void {\n\t\tconst now = Date.now();\n\t\t// Keep used codes until they expire, to detect reuse.\n\t\tfor (const [key, c] of this.#codes) {\n\t\t\tif (c.expiresAt <= now) this.#codes.delete(key);\n\t\t}\n\t\tif (force && this.#codes.size >= MAX_CODES) {\n\t\t\tconst drop = this.#codes.size - MAX_CODES + 1;\n\t\t\tfor (const key of [...this.#codes.keys()].slice(0, drop)) {\n\t\t\t\tthis.#codes.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Drop expired state; the relay calls it periodically. */\n\tsweep(): void {\n\t\tthis.#sweepPending();\n\t\tthis.#sweepCodes();\n\t\tconst now = Date.now();\n\t\tthis.#viewsPerIp.sweep(now);\n\t\tthis.#attemptsPerIp.sweep(now);\n\t\tthis.#guessesPerAddressIp.sweep(now);\n\t\tthis.#guessesPerAddress.sweep(now);\n\t\tthis.#tokenPerIp.sweep(now);\n\t}\n}\n",
|
|
11
|
+
"/**\n * The relay's OAuth 2.1 authorization server (DEC-006, DEC-015, DEC-031),\n * written without an OAuth library:\n *\n * - RFC 9728 protected-resource metadata per address, RFC 8414 server metadata;\n * - clients only through Client ID Metadata Documents (`cimd.ts`);\n * - `/authorize` with PKCE S256 only, exact redirect URIs (loopback port\n * relaxed), `resource` bound to one address (RFC 8707), `iss` in every\n * response (RFC 9207), and the pairing step of the address's site (DEC-042);\n * - `/token` for the authorization code and rotating refresh tokens (DEC-029);\n * - `/revoke` (RFC 7009).\n */\n\nimport { timingSafeEqual } from \"node:crypto\";\nimport { isAddressId, shortAddress } from \"../address.ts\";\nimport type { PairingKind, RelayConfig, Site } from \"../config.ts\";\nimport type { Logger } from \"../log.ts\";\nimport type { GrantInfo } from \"../protocol.ts\";\nimport { RateLimiter } from \"../ratelimit.ts\";\nimport type { TokenRecord, TokenStore } from \"../store/types.ts\";\nimport { hashToken, issueTokenPair, newId } from \"../tokens.ts\";\nimport {\n\ttype CimdTestMode,\n\ttype ClientMetadata,\n\tClientMetadataError,\n\tClientMetadataFetcher,\n\tredirectUriMatches,\n} from \"./cimd.ts\";\nimport { AUTHORIZE_CSS, escapeHtml, pageHeaders, renderPage } from \"./html.ts\";\nimport {\n\tPAIRING_METHODS,\n\ttype PairingMethod,\n\ttype PairingTarget,\n} from \"./pairing.ts\";\n\n/** The only scope: calling the page's tools. */\nexport const SCOPE = \"tools\";\n\n/** How long a user has to finish the `/authorize` page. */\nconst PENDING_TTL_MS = 10 * 60_000;\n/** Authorization codes are single-use and short-lived (RFC 6749 §4.1.2). */\nconst AUTH_CODE_TTL_MS = 60_000;\nconst MAX_PENDING = 10_000;\n/** Open authorization requests per IP (prefix) and per address (DEC-061). */\nconst MAX_PENDING_PER_IP = 10;\nconst MAX_PENDING_PER_ADDRESS = 20;\nconst MAX_CODES = 10_000;\nconst MAX_FORM_BYTES = 8192;\nconst MAX_STATE_LENGTH = 1024;\n\n/** A tab session as the authorization server sees it. */\nexport interface AuthorizeSession extends PairingTarget {\n\treadonly origin: string;\n\treadonly appName: string | undefined;\n\treadonly site: Site;\n}\n\nexport interface AuthorizationHost {\n\treadonly config: RelayConfig;\n\treadonly logger: Logger;\n\treadonly store: TokenStore;\n\tpublicUrl(): string;\n\t/** The connected (ready) tab session of an address. */\n\tsession(addressId: string): AuthorizeSession | undefined;\n\t/** Tell the address's tab, if connected. */\n\tgrantAdded(addressId: string, grant: GrantInfo): void;\n\tgrantRemoved(addressId: string, grantId: string, reason: string): void;\n}\n\n/** Test-only settings; never reachable from configuration. */\nexport interface AuthorizationTestMode {\n\tcimd?: CimdTestMode;\n\tauthCodeTtlMs?: number;\n\t/** Replace the pairing methods (a stub method proves the server needs no codes). */\n\tpairingMethods?: Partial<Record<PairingKind, PairingMethod>>;\n}\n\ninterface AuthorizationRequest {\n\tclient: ClientMetadata;\n\tredirectUri: string;\n\tstate: string | undefined;\n\tcodeChallenge: string;\n\taddressId: string;\n\tresource: string;\n\tscopes: string[];\n}\n\ninterface Pending extends AuthorizationRequest {\n\tid: string;\n\texpiresAt: number;\n\t/** The IP (prefix) key that opened it, for the per-IP cap. */\n\tip: string;\n}\n\ninterface IssuedCode extends AuthorizationRequest {\n\texpiresAt: number;\n\tused: boolean;\n\tgrantId?: string;\n}\n\nclass OAuthError extends Error {\n\treadonly status: number;\n\treadonly code: string;\n\tconstructor(status: number, code: string, description: string) {\n\t\tsuper(description);\n\t\tthis.status = status;\n\t\tthis.code = code;\n\t}\n}\n\nfunction constantTimeEqual(a: string, b: string): boolean {\n\tconst x = Buffer.from(a);\n\tconst y = Buffer.from(b);\n\treturn x.length === y.length && timingSafeEqual(x, y);\n}\n\n/** BASE64URL(SHA256(verifier)) (RFC 7636 §4.6). */\nexport function s256(verifier: string): string {\n\treturn new Bun.CryptoHasher(\"sha256\")\n\t\t.update(verifier)\n\t\t.digest()\n\t\t.toBase64({ alphabet: \"base64url\", omitPadding: true });\n}\n\n/** RFC 7636 §4.1: 43-128 unreserved characters. */\nconst VERIFIER = /^[A-Za-z0-9\\-._~]{43,128}$/;\n\n/** Parameters, refusing duplicates (RFC 6749 §3.1, §3.2). */\nfunction single(\n\tparams: URLSearchParams,\n\tnames: readonly string[],\n): Record<string, string | undefined> | { duplicate: string } {\n\tconst out: Record<string, string | undefined> = {};\n\tfor (const name of names) {\n\t\tconst values = params.getAll(name);\n\t\tif (values.length > 1) return { duplicate: name };\n\t\tconst value = values[0];\n\t\tout[name] = value === undefined || value === \"\" ? undefined : value;\n\t}\n\treturn out;\n}\n\nfunction random(bytes: number): string {\n\treturn crypto\n\t\t.getRandomValues(new Uint8Array(bytes))\n\t\t.toBase64({ alphabet: \"base64url\", omitPadding: true });\n}\n\n/** The origin a redirect URI sends the browser to, for CSP `form-action`. */\nfunction formTarget(redirectUri: string): string {\n\ttry {\n\t\tconst u = new URL(redirectUri);\n\t\treturn u.protocol === \"http:\" || u.protocol === \"https:\"\n\t\t\t? u.origin\n\t\t\t: u.protocol;\n\t} catch {\n\t\treturn \"'none'\";\n\t}\n}\n\nfunction hostOf(url: string): string {\n\ttry {\n\t\tconst u = new URL(url);\n\t\treturn u.host || u.protocol;\n\t} catch {\n\t\treturn url;\n\t}\n}\n\n/** The OAuth endpoints and pages, mounted by the relay. */\nexport class AuthorizationServer {\n\treadonly #host: AuthorizationHost;\n\treadonly #cimd: ClientMetadataFetcher;\n\t/** Insertion order is expiry order (one lifetime for all), so sweeps stop early. */\n\treadonly #pending = new Map<string, Pending>();\n\treadonly #pendingPerIp = new Map<string, number>();\n\treadonly #pendingPerAddress = new Map<string, number>();\n\treadonly #codes = new Map<string, IssuedCode>();\n\treadonly #authCodeTtlMs: number;\n\treadonly #methods: Partial<Record<PairingKind, PairingMethod>>;\n\treadonly #csrfSecret = random(32);\n\t/** `/authorize` page loads per IP. */\n\treadonly #viewsPerIp = new RateLimiter({\n\t\tcapacity: 30,\n\t\trefillPerSecond: 0.5,\n\t});\n\t/** Form posts per IP (every action; locks out only that network). */\n\treadonly #attemptsPerIp = new RateLimiter({\n\t\tcapacity: 20,\n\t\trefillPerSecond: 0.1,\n\t});\n\t/**\n\t * Code guesses (well-formed, against an active code) per address and IP:\n\t * one network cannot use up an address's allowance alone (DEC-061).\n\t */\n\treadonly #guessesPerAddressIp = new RateLimiter({\n\t\tcapacity: 10,\n\t\trefillPerSecond: 1 / 60,\n\t});\n\t/** Code guesses per address from everywhere: the brute-force cap (A1). */\n\treadonly #guessesPerAddress = new RateLimiter({\n\t\tcapacity: 30,\n\t\trefillPerSecond: 1 / 30,\n\t});\n\treadonly #tokenPerIp = new RateLimiter({ capacity: 30, refillPerSecond: 1 });\n\n\tconstructor(host: AuthorizationHost, testMode?: AuthorizationTestMode) {\n\t\tthis.#host = host;\n\t\tthis.#authCodeTtlMs = testMode?.authCodeTtlMs ?? AUTH_CODE_TTL_MS;\n\t\tthis.#methods = testMode?.pairingMethods ?? PAIRING_METHODS;\n\t\tthis.#cimd = new ClientMetadataFetcher({\n\t\t\tallowedHosts: host.config.clientIdHosts,\n\t\t\tlogger: host.logger,\n\t\t\t...(testMode?.cimd === undefined ? {} : { testMode: testMode.cimd }),\n\t\t});\n\t}\n\n\tget #issuer(): string {\n\t\treturn this.#host.publicUrl();\n\t}\n\n\t#cors(): Record<string, string> {\n\t\treturn this.#host.config.cors ? { \"access-control-allow-origin\": \"*\" } : {};\n\t}\n\n\t#json(\n\t\tstatus: number,\n\t\tvalue: unknown,\n\t\theaders: Record<string, string> = {},\n\t): Response {\n\t\treturn new Response(JSON.stringify(value), {\n\t\t\tstatus,\n\t\t\theaders: {\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t...this.#cors(),\n\t\t\t\t...headers,\n\t\t\t},\n\t\t});\n\t}\n\n\t/** CORS preflight for the metadata, token and revoke endpoints. */\n\tpreflight(methods: string): Response {\n\t\tif (!this.#host.config.cors) {\n\t\t\treturn new Response(null, { status: 405, headers: { allow: methods } });\n\t\t}\n\t\treturn new Response(null, {\n\t\t\tstatus: 204,\n\t\t\theaders: {\n\t\t\t\t...this.#cors(),\n\t\t\t\t\"access-control-allow-methods\": `${methods}, OPTIONS`,\n\t\t\t\t\"access-control-allow-headers\":\n\t\t\t\t\t\"authorization, content-type, mcp-protocol-version\",\n\t\t\t\t\"access-control-max-age\": \"600\",\n\t\t\t},\n\t\t});\n\t}\n\n\t// RFC 9728 and RFC 8414\n\n\t/** `/.well-known/oauth-protected-resource/a/{id}/mcp`. */\n\tprotectedResource(addressId: string): Response {\n\t\tif (!isAddressId(addressId))\n\t\t\treturn new Response(\"Not found\", { status: 404 });\n\t\treturn this.#json(\n\t\t\t200,\n\t\t\t{\n\t\t\t\tresource: `${this.#issuer}/a/${addressId}/mcp`,\n\t\t\t\tauthorization_servers: [this.#issuer],\n\t\t\t\tscopes_supported: [SCOPE],\n\t\t\t\tbearer_methods_supported: [\"header\"],\n\t\t\t\tresource_name: \"Tools of a web page (tab-mcp)\",\n\t\t\t},\n\t\t\t{ \"cache-control\": \"public, max-age=3600\" },\n\t\t);\n\t}\n\n\t/** `/.well-known/oauth-authorization-server`. */\n\tmetadata(): Response {\n\t\tconst issuer = this.#issuer;\n\t\treturn this.#json(\n\t\t\t200,\n\t\t\t{\n\t\t\t\tissuer,\n\t\t\t\tauthorization_endpoint: `${issuer}/authorize`,\n\t\t\t\ttoken_endpoint: `${issuer}/token`,\n\t\t\t\trevocation_endpoint: `${issuer}/revoke`,\n\t\t\t\tresponse_types_supported: [\"code\"],\n\t\t\t\tresponse_modes_supported: [\"query\"],\n\t\t\t\tgrant_types_supported: [\"authorization_code\", \"refresh_token\"],\n\t\t\t\tcode_challenge_methods_supported: [\"S256\"],\n\t\t\t\ttoken_endpoint_auth_methods_supported: [\"none\"],\n\t\t\t\trevocation_endpoint_auth_methods_supported: [\"none\"],\n\t\t\t\tscopes_supported: [SCOPE],\n\t\t\t\tclient_id_metadata_document_supported: true,\n\t\t\t\tauthorization_response_iss_parameter_supported: true,\n\t\t\t\tservice_documentation: \"https://github.com/ractive/tab-mcp\",\n\t\t\t},\n\t\t\t{ \"cache-control\": \"public, max-age=3600\" },\n\t\t);\n\t}\n\n\tstylesheet(): Response {\n\t\treturn new Response(AUTHORIZE_CSS, {\n\t\t\theaders: {\n\t\t\t\t\"content-type\": \"text/css; charset=utf-8\",\n\t\t\t\t\"cache-control\": \"public, max-age=3600\",\n\t\t\t\t\"x-content-type-options\": \"nosniff\",\n\t\t\t},\n\t\t});\n\t}\n\n\t// /authorize\n\n\t#page(\n\t\tstatus: number,\n\t\ttitle: string,\n\t\tbody: string,\n\t\tformTargets: readonly string[] = [],\n\t\textraHeaders: Record<string, string> = {},\n\t): Response {\n\t\tconst headers = pageHeaders(formTargets);\n\t\tfor (const [k, v] of Object.entries(extraHeaders)) headers.append(k, v);\n\t\treturn new Response(renderPage(title, body), { status, headers });\n\t}\n\n\t/** An error shown on the page: the redirect URI is not trusted (yet). */\n\t#errorPage(status: number, message: string): Response {\n\t\treturn this.#page(\n\t\t\tstatus,\n\t\t\t\"This connection cannot be made\",\n\t\t\t`<h1>This connection cannot be made</h1>\n<p role=\"alert\">${escapeHtml(message)}</p>\n<p>Go back to your AI app and try again. If it keeps happening, the AI app may not work with this relay.</p>`,\n\t\t);\n\t}\n\n\t/** The client's redirect URI with `error` (RFC 6749 §4.1.2.1) and `iss`. */\n\t#errorUrl(\n\t\tredirectUri: string,\n\t\tstate: string | undefined,\n\t\terror: string,\n\t\tdescription: string,\n\t): string {\n\t\tconst url = new URL(redirectUri);\n\t\tconst params: Record<string, string> = {\n\t\t\terror,\n\t\t\terror_description: description,\n\t\t\t...(state === undefined ? {} : { state }),\n\t\t\tiss: this.#issuer,\n\t\t};\n\t\tfor (const [k, v] of Object.entries(params)) url.searchParams.append(k, v);\n\t\treturn url.href;\n\t}\n\n\t/**\n\t * An invalid request from a client: not redirected automatically, so the\n\t * relay is no open redirector for self-published clients (RFC 9700\n\t * §4.11.2). The page names the destination and links to it (DEC-064).\n\t */\n\t#invalidRequestPage(\n\t\tredirectUri: string,\n\t\tstate: string | undefined,\n\t\terror: string,\n\t\tdescription: string,\n\t): Response {\n\t\tconst url = this.#errorUrl(redirectUri, state, error, description);\n\t\tconst host = hostOf(redirectUri);\n\t\treturn this.#page(\n\t\t\t400,\n\t\t\t\"This connection cannot be made\",\n\t\t\t`<h1>This connection cannot be made</h1>\n<p role=\"alert\">The AI app sent a request this relay cannot accept: ${escapeHtml(description)} (${escapeHtml(error)}).</p>\n<p>You can go back to the AI app at ${escapeHtml(host)} to tell it, or close this page.</p>\n<div class=\"actions\"><a class=\"button\" href=\"${escapeHtml(url)}\">Go back to ${escapeHtml(host)}</a></div>`,\n\t\t);\n\t}\n\n\t/** The user's own Cancel: back to the client at once (`access_denied`). */\n\t#redirectError(\n\t\tredirectUri: string,\n\t\tstate: string | undefined,\n\t\terror: string,\n\t\tdescription: string,\n\t): Response {\n\t\treturn new Response(null, {\n\t\t\tstatus: 303,\n\t\t\theaders: {\n\t\t\t\tlocation: this.#errorUrl(redirectUri, state, error, description),\n\t\t\t\t\"cache-control\": \"no-store\",\n\t\t\t\t\"referrer-policy\": \"no-referrer\",\n\t\t\t},\n\t\t});\n\t}\n\n\t#redirect(redirectUri: string, params: Record<string, string>): Response {\n\t\tconst url = new URL(redirectUri);\n\t\tfor (const [k, v] of Object.entries(params)) url.searchParams.append(k, v);\n\t\treturn new Response(null, {\n\t\t\tstatus: 303,\n\t\t\theaders: {\n\t\t\t\tlocation: url.href,\n\t\t\t\t\"cache-control\": \"no-store\",\n\t\t\t\t\"referrer-policy\": \"no-referrer\",\n\t\t\t},\n\t\t});\n\t}\n\n\t/** GET `/authorize`: check the request, then show the pairing page. */\n\tasync authorize(req: Request, ip: string): Promise<Response> {\n\t\tif (!this.#viewsPerIp.take(ip)) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t429,\n\t\t\t\t\"Too many requests from your network. Wait a minute and try again.\",\n\t\t\t);\n\t\t}\n\t\tconst query = new URL(req.url).searchParams;\n\t\tconst p = single(query, [\n\t\t\t\"response_type\",\n\t\t\t\"client_id\",\n\t\t\t\"redirect_uri\",\n\t\t\t\"code_challenge\",\n\t\t\t\"code_challenge_method\",\n\t\t\t\"state\",\n\t\t\t\"resource\",\n\t\t\t\"scope\",\n\t\t]);\n\t\tif (\"duplicate\" in p) {\n\t\t\tif (p.duplicate === \"client_id\" || p.duplicate === \"redirect_uri\") {\n\t\t\t\treturn this.#errorPage(400, `The request names ${p.duplicate} twice.`);\n\t\t\t}\n\t\t}\n\t\tconst clientId = \"duplicate\" in p ? query.get(\"client_id\") : p[\"client_id\"];\n\t\tconst redirectUri =\n\t\t\t\"duplicate\" in p ? query.get(\"redirect_uri\") : p[\"redirect_uri\"];\n\t\tif (clientId === undefined || clientId === null) {\n\t\t\treturn this.#errorPage(400, \"The request has no client_id.\");\n\t\t}\n\t\tlet client: ClientMetadata;\n\t\ttry {\n\t\t\tclient = await this.#cimd.get(clientId);\n\t\t} catch (error) {\n\t\t\tif (error instanceof ClientMetadataError) {\n\t\t\t\tthis.#host.logger.info(\"oauth.client_refused\", {\n\t\t\t\t\treason: error.reason,\n\t\t\t\t\thost: hostOf(clientId).slice(0, 100),\n\t\t\t\t});\n\t\t\t\treturn this.#errorPage(400, error.message);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tif (redirectUri === undefined || redirectUri === null) {\n\t\t\treturn this.#errorPage(400, \"The request has no redirect_uri.\");\n\t\t}\n\t\tif (!client.redirectUris.some((r) => redirectUriMatches(redirectUri, r))) {\n\t\t\tthis.#host.logger.info(\"oauth.client_refused\", {\n\t\t\t\treason: \"redirect_uri\",\n\t\t\t\thost: client.host,\n\t\t\t});\n\t\t\treturn this.#errorPage(\n\t\t\t\t400,\n\t\t\t\t`${client.name} asked to return to an address it has not registered (${hostOf(redirectUri)}).`,\n\t\t\t);\n\t\t}\n\t\t// From here on errors go back to the (now trusted) redirect URI.\n\t\tconst state = \"duplicate\" in p ? undefined : p[\"state\"];\n\t\tconst fail = (error: string, description: string) =>\n\t\t\tthis.#invalidRequestPage(redirectUri, state, error, description);\n\t\tif (\"duplicate\" in p) {\n\t\t\treturn fail(\"invalid_request\", `${p.duplicate} was sent more than once`);\n\t\t}\n\t\tif (state !== undefined && state.length > MAX_STATE_LENGTH) {\n\t\t\treturn fail(\"invalid_request\", \"state is too long\");\n\t\t}\n\t\tif (p[\"response_type\"] !== \"code\") {\n\t\t\treturn fail(\n\t\t\t\t\"unsupported_response_type\",\n\t\t\t\t\"only response_type=code is supported\",\n\t\t\t);\n\t\t}\n\t\tconst challenge = p[\"code_challenge\"];\n\t\tif (challenge === undefined) {\n\t\t\treturn fail(\"invalid_request\", \"code_challenge is required (PKCE)\");\n\t\t}\n\t\tif (p[\"code_challenge_method\"] !== \"S256\") {\n\t\t\treturn fail(\"invalid_request\", \"code_challenge_method must be S256\");\n\t\t}\n\t\tif (!/^[A-Za-z0-9\\-._~]{43,128}$/.test(challenge)) {\n\t\t\treturn fail(\"invalid_request\", \"code_challenge is malformed\");\n\t\t}\n\t\tconst resource = p[\"resource\"];\n\t\tconst addressId = this.#addressOf(resource);\n\t\tif (resource === undefined || addressId === undefined) {\n\t\t\treturn fail(\n\t\t\t\t\"invalid_target\",\n\t\t\t\t\"resource must be the MCP address of a page on this relay\",\n\t\t\t);\n\t\t}\n\t\tconst scopes = this.#grantedScopes(p[\"scope\"]);\n\t\tif (scopes === undefined) {\n\t\t\treturn fail(\"invalid_scope\", `the only scope is \"${SCOPE}\"`);\n\t\t}\n\n\t\t// No connected tab: nothing to pair with, so nothing is kept (DEC-061).\n\t\tif (this.#host.session(addressId) === undefined) {\n\t\t\treturn this.#offlinePage(\n\t\t\t\tclient,\n\t\t\t\t`/authorize${new URL(req.url).search}`,\n\t\t\t\tthis.#errorUrl(\n\t\t\t\t\tredirectUri,\n\t\t\t\t\tstate,\n\t\t\t\t\t\"access_denied\",\n\t\t\t\t\t\"the user cancelled the connection\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tthis.#sweepPending();\n\t\tif (\n\t\t\tthis.#pending.size >= MAX_PENDING ||\n\t\t\t(this.#pendingPerIp.get(ip) ?? 0) >= MAX_PENDING_PER_IP ||\n\t\t\t(this.#pendingPerAddress.get(addressId) ?? 0) >= MAX_PENDING_PER_ADDRESS\n\t\t) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t429,\n\t\t\t\t\"Too many connection requests are open right now. Wait a few minutes and try again.\",\n\t\t\t);\n\t\t}\n\t\tconst pending: Pending = {\n\t\t\tid: random(24),\n\t\t\texpiresAt: Date.now() + PENDING_TTL_MS,\n\t\t\tip,\n\t\t\tclient,\n\t\t\tredirectUri,\n\t\t\tstate,\n\t\t\tcodeChallenge: challenge,\n\t\t\taddressId,\n\t\t\tresource,\n\t\t\tscopes,\n\t\t};\n\t\tthis.#addPending(pending);\n\t\tconst browser = this.#browserId(req);\n\t\treturn this.#pairingPage(\n\t\t\tpending,\n\t\t\tbrowser.id,\n\t\t\tundefined,\n\t\t\t200,\n\t\t\tbrowser.cookie,\n\t\t);\n\t}\n\n\t#addPending(p: Pending): void {\n\t\tthis.#pending.set(p.id, p);\n\t\tthis.#pendingPerIp.set(p.ip, (this.#pendingPerIp.get(p.ip) ?? 0) + 1);\n\t\tthis.#pendingPerAddress.set(\n\t\t\tp.addressId,\n\t\t\t(this.#pendingPerAddress.get(p.addressId) ?? 0) + 1,\n\t\t);\n\t}\n\n\t#dropPending(p: Pending): void {\n\t\tif (!this.#pending.delete(p.id)) return;\n\t\tconst dec = (map: Map<string, number>, key: string) => {\n\t\t\tconst n = (map.get(key) ?? 1) - 1;\n\t\t\tif (n <= 0) map.delete(key);\n\t\t\telse map.set(key, n);\n\t\t};\n\t\tdec(this.#pendingPerIp, p.ip);\n\t\tdec(this.#pendingPerAddress, p.addressId);\n\t}\n\n\t/** The tab is not connected: try again by loading the page again. */\n\t#offlinePage(\n\t\tclient: ClientMetadata,\n\t\tretryUrl: string,\n\t\tcancelUrl: string,\n\t\terror?: string,\n\t): Response {\n\t\tconst errorHtml =\n\t\t\terror === undefined\n\t\t\t\t? \"\"\n\t\t\t\t: `<p class=\"error\" role=\"alert\">${escapeHtml(error)}</p>`;\n\t\tconst body = `<h1>Open the page first</h1>\n${errorHtml}\n<p><strong>${escapeHtml(client.name)}</strong> (${escapeHtml(client.host)}) wants to use the tools of a web page, but that page is not open right now.</p>\n<p>Open the page, click “Connect your AI app”, then try again here.</p>\n<div class=\"actions\">\n<a class=\"button primary\" href=\"${escapeHtml(retryUrl)}\">Try again</a>\n<a class=\"button\" href=\"${escapeHtml(cancelUrl)}\">Cancel</a>\n</div>`;\n\t\treturn this.#page(200, \"Open the page first\", body);\n\t}\n\n\t/** POST `/authorize`: the pairing form (connect, cancel, try again). */\n\tasync authorizeSubmit(req: Request, ip: string): Promise<Response> {\n\t\t// Only our own form may post here (defence in depth beside the token).\n\t\tconst origin = req.headers.get(\"origin\");\n\t\tconst site = req.headers.get(\"sec-fetch-site\");\n\t\tif (\n\t\t\t(origin !== null && origin !== this.#issuer) ||\n\t\t\t(site !== null && site !== \"same-origin\")\n\t\t) {\n\t\t\treturn this.#errorPage(403, \"This form can only be sent from this page.\");\n\t\t}\n\t\tif (!this.#attemptsPerIp.take(ip)) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t429,\n\t\t\t\t\"Too many attempts from your network. Wait a few minutes, then start again from your AI app.\",\n\t\t\t);\n\t\t}\n\t\tconst type = (req.headers.get(\"content-type\") ?? \"\").split(\";\")[0]?.trim();\n\t\tif (type !== \"application/x-www-form-urlencoded\") {\n\t\t\treturn this.#errorPage(400, \"The form was not sent correctly.\");\n\t\t}\n\t\tconst text = await this.#readForm(req);\n\t\tif (text === undefined) {\n\t\t\treturn this.#errorPage(413, \"The form was too large.\");\n\t\t}\n\t\tconst form = new URLSearchParams(text);\n\t\tconst pending = this.#pending.get(form.get(\"request_id\") ?? \"\");\n\t\tif (pending === undefined || pending.expiresAt <= Date.now()) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t400,\n\t\t\t\t\"This connection request has expired or was already used.\",\n\t\t\t);\n\t\t}\n\t\tconst browser = this.#browserId(req);\n\t\tconst csrf = form.get(\"csrf\") ?? \"\";\n\t\tif (\n\t\t\tbrowser.cookie !== undefined ||\n\t\t\t!Bun.CSRF.verify(csrf, {\n\t\t\t\tsecret: this.#csrfSecret,\n\t\t\t\tsessionId: `${pending.id}.${browser.id}`,\n\t\t\t\tmaxAge: PENDING_TTL_MS,\n\t\t\t})\n\t\t) {\n\t\t\t// A new cookie means the browser did not send ours: not the same visit.\n\t\t\treturn this.#errorPage(\n\t\t\t\t403,\n\t\t\t\t\"The form could not be checked. Your browser may block cookies for this site.\",\n\t\t\t);\n\t\t}\n\n\t\tconst action = form.get(\"action\");\n\t\tif (action === \"cancel\") {\n\t\t\tthis.#dropPending(pending);\n\t\t\tthis.#host.logger.info(\"oauth.cancelled\", {\n\t\t\t\taddress: shortAddress(pending.addressId),\n\t\t\t\tclient: pending.client.host,\n\t\t\t});\n\t\t\treturn this.#redirectError(\n\t\t\t\tpending.redirectUri,\n\t\t\t\tpending.state,\n\t\t\t\t\"access_denied\",\n\t\t\t\t\"the user cancelled the connection\",\n\t\t\t);\n\t\t}\n\t\tif (action !== \"connect\") {\n\t\t\treturn this.#pairingPage(pending, browser.id);\n\t\t}\n\n\t\tconst session = this.#host.session(pending.addressId);\n\t\tif (session === undefined) {\n\t\t\treturn this.#pairingPage(\n\t\t\t\tpending,\n\t\t\t\tbrowser.id,\n\t\t\t\t\"The page is still not open.\",\n\t\t\t);\n\t\t}\n\t\tconst method = this.#methods[session.site.pairing];\n\t\tif (method === undefined) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t500,\n\t\t\t\t\"This page's pairing method is not available.\",\n\t\t\t);\n\t\t}\n\t\t// Only a real guess is charged: the method calls this right before it\n\t\t// compares a well-formed answer (DEC-061).\n\t\tconst admit = () =>\n\t\t\tthis.#guessesPerAddressIp.take(`${pending.addressId}|${ip}`) &&\n\t\t\tthis.#guessesPerAddress.take(pending.addressId);\n\t\tconst result = await method.check(session, form, admit);\n\t\tif (!result.ok) {\n\t\t\tthis.#host.logger.info(\"oauth.pairing_failed\", {\n\t\t\t\taddress: shortAddress(pending.addressId),\n\t\t\t\tclient: pending.client.host,\n\t\t\t\treason: result.reason,\n\t\t\t});\n\t\t\treturn this.#pairingPage(\n\t\t\t\tpending,\n\t\t\t\tbrowser.id,\n\t\t\t\tresult.message,\n\t\t\t\tresult.reason === \"rate_limited\" ? 429 : 400,\n\t\t\t);\n\t\t}\n\n\t\tthis.#dropPending(pending);\n\t\tconst code = random(32);\n\t\tif (this.#codes.size >= MAX_CODES) this.#sweepCodes(true);\n\t\tconst { id: _id, expiresAt: _expires, ip: _ip, ...request } = pending;\n\t\tthis.#codes.set(hashToken(code), {\n\t\t\t...request,\n\t\t\texpiresAt: Date.now() + this.#authCodeTtlMs,\n\t\t\tused: false,\n\t\t});\n\t\tthis.#host.logger.info(\"oauth.paired\", {\n\t\t\taddress: shortAddress(pending.addressId),\n\t\t\tclient: pending.client.host,\n\t\t\tmethod: method.kind,\n\t\t});\n\t\treturn this.#redirect(pending.redirectUri, {\n\t\t\tcode,\n\t\t\t...(pending.state === undefined ? {} : { state: pending.state }),\n\t\t\tiss: this.#issuer,\n\t\t});\n\t}\n\n\t#addressOf(resource: string | undefined): string | undefined {\n\t\tif (resource === undefined) return undefined;\n\t\tconst prefix = `${this.#issuer}/a/`;\n\t\tif (!resource.startsWith(prefix) || !resource.endsWith(\"/mcp\")) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst id = resource.slice(prefix.length, -\"/mcp\".length);\n\t\treturn isAddressId(id) ? id : undefined;\n\t}\n\n\t/** Requested scopes reduced to what exists; `undefined` = none of them. */\n\t#grantedScopes(scope: string | undefined): string[] | undefined {\n\t\tif (scope === undefined) return [SCOPE];\n\t\tconst requested = scope.split(\" \").filter((s) => s !== \"\");\n\t\tif (requested.length === 0) return [SCOPE];\n\t\treturn requested.includes(SCOPE) ? [SCOPE] : undefined;\n\t}\n\n\t/** The browser's visit id from our cookie, or a new one with its cookie. */\n\t#browserId(req: Request): { id: string; cookie?: string } {\n\t\tconst name = this.#cookieName();\n\t\tconst header = req.headers.get(\"cookie\") ?? \"\";\n\t\tfor (const part of header.split(\";\")) {\n\t\t\tconst [k, v] = part.trim().split(\"=\");\n\t\t\tif (k === name && v !== undefined && /^[A-Za-z0-9_-]{22}$/.test(v)) {\n\t\t\t\treturn { id: v };\n\t\t\t}\n\t\t}\n\t\tconst id = random(16);\n\t\tconst secure = this.#issuer.startsWith(\"https:\") ? \"; Secure\" : \"\";\n\t\treturn {\n\t\t\tid,\n\t\t\tcookie: `${name}=${id}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${PENDING_TTL_MS / 1000}${secure}`,\n\t\t};\n\t}\n\n\t#cookieName(): string {\n\t\treturn this.#issuer.startsWith(\"https:\")\n\t\t\t? \"__Host-tab-mcp-authorize\"\n\t\t\t: \"tab-mcp-authorize\";\n\t}\n\n\tasync #readForm(req: Request): Promise<string | undefined> {\n\t\tconst length = Number(req.headers.get(\"content-length\") ?? \"0\");\n\t\tif (length > MAX_FORM_BYTES) return undefined;\n\t\tconst bytes = await req.arrayBuffer().catch(() => new ArrayBuffer(0));\n\t\tif (bytes.byteLength > MAX_FORM_BYTES) return undefined;\n\t\treturn new TextDecoder().decode(bytes);\n\t}\n\n\t#pairingPage(\n\t\tpending: Pending,\n\t\tbrowserId: string,\n\t\terror?: string,\n\t\tstatus = 200,\n\t\tcookie?: string,\n\t): Response {\n\t\tconst csrf = Bun.CSRF.generate(this.#csrfSecret, {\n\t\t\tsessionId: `${pending.id}.${browserId}`,\n\t\t\texpiresIn: PENDING_TTL_MS,\n\t\t});\n\t\tconst client = pending.client;\n\t\tconst clientLabel = `<strong>${escapeHtml(client.name)}</strong> (${escapeHtml(client.host)})`;\n\t\tconst hidden = `<input type=\"hidden\" name=\"request_id\" value=\"${escapeHtml(pending.id)}\">\n<input type=\"hidden\" name=\"csrf\" value=\"${escapeHtml(csrf)}\">`;\n\t\tconst errorHtml =\n\t\t\terror === undefined\n\t\t\t\t? \"\"\n\t\t\t\t: `<p class=\"error\" role=\"alert\" id=\"error\">${escapeHtml(error)}</p>`;\n\t\tconst extra = cookie === undefined ? {} : { \"set-cookie\": cookie };\n\t\tconst targets = [formTarget(pending.redirectUri)];\n\t\tconst cancel = `<button type=\"submit\" class=\"secondary\" name=\"action\" value=\"cancel\" formnovalidate>Cancel</button>`;\n\n\t\tconst session = this.#host.session(pending.addressId);\n\t\tif (session === undefined) {\n\t\t\t// The tab went away after the page was opened: keep the request,\n\t\t\t// so Try again (a post) can continue once the tab is back.\n\t\t\tconst body = `<h1>Open the page first</h1>\n${errorHtml}\n<p>${clientLabel} wants to use the tools of a web page, but that page is not open right now.</p>\n<p>Open the page, click “Connect your AI app”, then try again here.</p>\n<form method=\"post\" action=\"/authorize\">\n${hidden}\n<div class=\"actions\">\n<button type=\"submit\" class=\"primary\" name=\"action\" value=\"retry\">Try again</button>\n${cancel}\n</div>\n</form>`;\n\t\t\treturn this.#page(status, \"Open the page first\", body, targets, extra);\n\t\t}\n\n\t\tconst method = this.#methods[session.site.pairing];\n\t\tif (method === undefined) {\n\t\t\treturn this.#errorPage(\n\t\t\t\t500,\n\t\t\t\t\"This page's pairing method is not available.\",\n\t\t\t);\n\t\t}\n\t\t// A browser always sends an Origin; only a non-browser tab on an open\n\t\t// relay has none.\n\t\tconst page =\n\t\t\tsession.origin === \"\"\n\t\t\t\t? \"a page that did not say where it runs\"\n\t\t\t\t: `<span class=\"origin\">${escapeHtml(session.origin)}</span>`;\n\t\tconst target =\n\t\t\tsession.appName === undefined\n\t\t\t\t? `tools from ${page}`\n\t\t\t\t: `<strong>${escapeHtml(session.appName)}</strong> on ${page}`;\n\t\t// The verified host is part of the heading and title, so a\n\t\t// self-declared name never stands alone (DEC-065).\n\t\tconst heading = `Connect ${client.name} from ${client.host}`;\n\t\tconst body = `<h1>${escapeHtml(heading)}</h1>\n<p>You're connecting ${clientLabel} to ${target}.</p>\n<p>${escapeHtml(client.name)} can then use this page's tools while the page is open. You can disconnect it in the page at any time.</p>\n${errorHtml}\n<form method=\"post\" action=\"/authorize\">\n${hidden}\n${method.render(session)}\n<div class=\"actions\">\n<button type=\"submit\" class=\"primary\" name=\"action\" value=\"connect\">Connect</button>\n${cancel}\n</div>\n</form>\n<p class=\"help\">After you connect, your browser goes back to ${escapeHtml(hostOf(pending.redirectUri))}. Only connect AI apps you started yourself.</p>`;\n\t\treturn this.#page(status, heading, body, targets, extra);\n\t}\n\n\t// /token\n\n\t/** POST `/token`. */\n\tasync token(req: Request, ip: string): Promise<Response> {\n\t\tconst noStore = { \"cache-control\": \"no-store\", pragma: \"no-cache\" };\n\t\ttry {\n\t\t\tif (!this.#tokenPerIp.take(ip)) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t429,\n\t\t\t\t\t\"temporarily_unavailable\",\n\t\t\t\t\t\"too many requests; try again shortly\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst params = await this.#formParams(req);\n\t\t\tconst p = single(params, [\n\t\t\t\t\"grant_type\",\n\t\t\t\t\"client_id\",\n\t\t\t\t\"code\",\n\t\t\t\t\"redirect_uri\",\n\t\t\t\t\"code_verifier\",\n\t\t\t\t\"refresh_token\",\n\t\t\t\t\"resource\",\n\t\t\t\t\"scope\",\n\t\t\t]);\n\t\t\tif (\"duplicate\" in p) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t400,\n\t\t\t\t\t\"invalid_request\",\n\t\t\t\t\t`${p.duplicate} was sent more than once`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst clientId = p[\"client_id\"];\n\t\t\tif (clientId === undefined) {\n\t\t\t\tthrow new OAuthError(400, \"invalid_request\", \"client_id is required\");\n\t\t\t}\n\t\t\tlet body: Record<string, unknown>;\n\t\t\tif (p[\"grant_type\"] === \"authorization_code\") {\n\t\t\t\tbody = await this.#codeGrant(p, clientId);\n\t\t\t} else if (p[\"grant_type\"] === \"refresh_token\") {\n\t\t\t\tbody = await this.#refreshGrant(p, clientId);\n\t\t\t} else if (p[\"grant_type\"] === undefined) {\n\t\t\t\tthrow new OAuthError(400, \"invalid_request\", \"grant_type is required\");\n\t\t\t} else {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t400,\n\t\t\t\t\t\"unsupported_grant_type\",\n\t\t\t\t\t\"only authorization_code and refresh_token are supported\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn this.#json(200, body, noStore);\n\t\t} catch (error) {\n\t\t\treturn this.#oauthErrorResponse(error, noStore);\n\t\t}\n\t}\n\n\t#oauthErrorResponse(\n\t\terror: unknown,\n\t\theaders: Record<string, string>,\n\t): Response {\n\t\tif (error instanceof OAuthError) {\n\t\t\tconst extra: Record<string, string> = { ...headers };\n\t\t\tif (error.status === 401)\n\t\t\t\textra[\"www-authenticate\"] = 'Basic realm=\"tab-mcp\"';\n\t\t\tif (error.status === 429 || error.status === 503)\n\t\t\t\textra[\"retry-after\"] = \"10\";\n\t\t\treturn this.#json(\n\t\t\t\terror.status,\n\t\t\t\t{ error: error.code, error_description: error.message },\n\t\t\t\textra,\n\t\t\t);\n\t\t}\n\t\tthis.#host.logger.error(\"oauth.error\", {\n\t\t\tmessage: error instanceof Error ? error.name : \"unknown\",\n\t\t});\n\t\treturn this.#json(\n\t\t\t503,\n\t\t\t{\n\t\t\t\terror: \"temporarily_unavailable\",\n\t\t\t\terror_description: \"the relay cannot issue tokens right now\",\n\t\t\t},\n\t\t\t{ ...headers, \"retry-after\": \"10\" },\n\t\t);\n\t}\n\n\t/** Form parameters of a token or revocation request (client auth `none` only). */\n\tasync #formParams(req: Request): Promise<URLSearchParams> {\n\t\tconst type = (req.headers.get(\"content-type\") ?? \"\").split(\";\")[0]?.trim();\n\t\tif (type !== \"application/x-www-form-urlencoded\") {\n\t\t\tthrow new OAuthError(\n\t\t\t\t400,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"the body must be application/x-www-form-urlencoded\",\n\t\t\t);\n\t\t}\n\t\tif (req.headers.get(\"authorization\") !== null) {\n\t\t\t// RFC 6749 §5.2: a client that tried to authenticate gets 401.\n\t\t\tthrow new OAuthError(\n\t\t\t\t401,\n\t\t\t\t\"invalid_client\",\n\t\t\t\t\"client authentication is not supported (token_endpoint_auth_method none)\",\n\t\t\t);\n\t\t}\n\t\tconst text = await this.#readForm(req);\n\t\tif (text === undefined) {\n\t\t\tthrow new OAuthError(413, \"invalid_request\", \"the request is too large\");\n\t\t}\n\t\tconst params = new URLSearchParams(text);\n\t\tif (params.has(\"client_secret\") || params.has(\"client_assertion\")) {\n\t\t\tthrow new OAuthError(\n\t\t\t\t400,\n\t\t\t\t\"invalid_client\",\n\t\t\t\t\"client authentication is not supported (token_endpoint_auth_method none)\",\n\t\t\t);\n\t\t}\n\t\treturn params;\n\t}\n\n\tasync #codeGrant(\n\t\tp: Record<string, string | undefined>,\n\t\tclientId: string,\n\t): Promise<Record<string, unknown>> {\n\t\tconst code = p[\"code\"];\n\t\tconst redirectUri = p[\"redirect_uri\"];\n\t\tconst verifier = p[\"code_verifier\"];\n\t\tif (\n\t\t\tcode === undefined ||\n\t\t\tredirectUri === undefined ||\n\t\t\tverifier === undefined\n\t\t) {\n\t\t\tthrow new OAuthError(\n\t\t\t\t400,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"code, redirect_uri and code_verifier are required\",\n\t\t\t);\n\t\t}\n\t\tconst key = hashToken(code);\n\t\tconst issued = this.#codes.get(key);\n\t\tconst invalid = (why: string) => new OAuthError(400, \"invalid_grant\", why);\n\t\tif (issued === undefined) throw invalid(\"the code is not valid\");\n\t\tif (issued.used) {\n\t\t\t// RFC 6749 §4.1.2: a code used twice revokes what it produced.\n\t\t\tif (issued.grantId !== undefined) {\n\t\t\t\tawait this.#revokeGrant(\n\t\t\t\t\tissued.addressId,\n\t\t\t\t\tissued.grantId,\n\t\t\t\t\t\"reuse_detected\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow invalid(\"the code was already used\");\n\t\t}\n\t\tissued.used = true; // a failed check below burns the code too\n\t\tif (issued.expiresAt <= Date.now()) throw invalid(\"the code has expired\");\n\t\tif (!constantTimeEqual(clientId, issued.client.clientId)) {\n\t\t\tthrow invalid(\"the code was issued to another client\");\n\t\t}\n\t\tif (redirectUri !== issued.redirectUri) {\n\t\t\tthrow invalid(\"redirect_uri does not match the authorization request\");\n\t\t}\n\t\tif (p[\"resource\"] !== undefined && p[\"resource\"] !== issued.resource) {\n\t\t\tthrow new OAuthError(\n\t\t\t\t400,\n\t\t\t\t\"invalid_target\",\n\t\t\t\t\"resource does not match the authorization request\",\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\t!VERIFIER.test(verifier) ||\n\t\t\t!constantTimeEqual(s256(verifier), issued.codeChallenge)\n\t\t) {\n\t\t\tthrow invalid(\"code_verifier does not match the code_challenge\");\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tconst grantId = newId(\"g\");\n\t\tissued.grantId = grantId;\n\t\tconst config = this.#host.config;\n\t\tconst tokens = await issueTokenPair(\n\t\t\tthis.#host.store,\n\t\t\t{\n\t\t\t\tgrantId,\n\t\t\t\taddressId: issued.addressId,\n\t\t\t\tclientId: issued.client.clientId,\n\t\t\t\tclientName: issued.client.name,\n\t\t\t\tscopes: issued.scopes,\n\t\t\t\tgrantCreatedAt: now,\n\t\t\t},\n\t\t\t{\n\t\t\t\taccessTtlMs: config.accessTokenTtlMs,\n\t\t\t\trefreshTtlMs: config.refreshTokenTtlMs,\n\t\t\t\tgrantEndsAt: now + config.grantLifetimeMs,\n\t\t\t\tnow,\n\t\t\t},\n\t\t);\n\t\tif (tokens === undefined) {\n\t\t\t// Revoked while the tokens were issued (code reuse, New address).\n\t\t\tthrow invalid(\"the connection was revoked\");\n\t\t}\n\t\tthis.#host.logger.info(\"oauth.grant_created\", {\n\t\t\taddress: shortAddress(issued.addressId),\n\t\t\tclient: issued.client.host,\n\t\t});\n\t\tthis.#host.grantAdded(issued.addressId, {\n\t\t\tgrantId,\n\t\t\tclient: {\n\t\t\t\tid: issued.client.clientId,\n\t\t\t\tname: issued.client.name,\n\t\t\t\thost: issued.client.host,\n\t\t\t},\n\t\t\tcreatedAt: new Date(now).toISOString(),\n\t\t});\n\t\treturn this.#tokenBody(tokens, issued.scopes);\n\t}\n\n\t#tokenBody(\n\t\ttokens: { accessToken: string; refreshToken: string; expiresIn: number },\n\t\tscopes: string[],\n\t): Record<string, unknown> {\n\t\treturn {\n\t\t\taccess_token: tokens.accessToken,\n\t\t\ttoken_type: \"Bearer\",\n\t\t\texpires_in: tokens.expiresIn,\n\t\t\trefresh_token: tokens.refreshToken,\n\t\t\tscope: scopes.join(\" \"),\n\t\t};\n\t}\n\n\tasync #refreshGrant(\n\t\tp: Record<string, string | undefined>,\n\t\tclientId: string,\n\t): Promise<Record<string, unknown>> {\n\t\tconst token = p[\"refresh_token\"];\n\t\tif (token === undefined) {\n\t\t\tthrow new OAuthError(400, \"invalid_request\", \"refresh_token is required\");\n\t\t}\n\t\tconst invalid = (why: string) => new OAuthError(400, \"invalid_grant\", why);\n\t\tconst hash = hashToken(token);\n\t\tconst record = await this.#host.store.get(hash);\n\t\tif (record === undefined || record.kind !== \"refresh\") {\n\t\t\tthrow invalid(\"the refresh token is not valid\");\n\t\t}\n\t\tif (!constantTimeEqual(clientId, record.clientId)) {\n\t\t\tthrow invalid(\"the refresh token was issued to another client\");\n\t\t}\n\t\tconst now = Date.now();\n\t\tif (record.expiresAt <= now) throw invalid(\"the refresh token has expired\");\n\t\tif (record.usedAt !== undefined) {\n\t\t\tawait this.#reuseDetected(record);\n\t\t\tthrow invalid(\n\t\t\t\t\"the refresh token was already used; the connection was revoked\",\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tp[\"resource\"] !== undefined &&\n\t\t\tp[\"resource\"] !== `${this.#issuer}/a/${record.addressId}/mcp`\n\t\t) {\n\t\t\tthrow new OAuthError(\n\t\t\t\t400,\n\t\t\t\t\"invalid_target\",\n\t\t\t\t\"resource is not the address this token belongs to\",\n\t\t\t);\n\t\t}\n\t\tconst scope = p[\"scope\"];\n\t\tif (scope !== undefined) {\n\t\t\tconst wanted = scope.split(\" \").filter((s) => s !== \"\");\n\t\t\tif (!wanted.every((s) => record.scopes.includes(s))) {\n\t\t\t\tthrow new OAuthError(400, \"invalid_scope\", \"scope exceeds the grant\");\n\t\t\t}\n\t\t}\n\t\t// Atomic: of two refreshes with the same token only one gets here.\n\t\tif (!(await this.#host.store.markUsed(hash, now))) {\n\t\t\tawait this.#reuseDetected(record);\n\t\t\tthrow invalid(\n\t\t\t\t\"the refresh token was already used; the connection was revoked\",\n\t\t\t);\n\t\t}\n\t\tconst tokens = await issueTokenPair(\n\t\t\tthis.#host.store,\n\t\t\t{\n\t\t\t\tgrantId: record.grantId,\n\t\t\t\taddressId: record.addressId,\n\t\t\t\tclientId: record.clientId,\n\t\t\t\tclientName: record.clientName,\n\t\t\t\tscopes: record.scopes,\n\t\t\t\tgrantCreatedAt: record.grantCreatedAt,\n\t\t\t},\n\t\t\t{\n\t\t\t\taccessTtlMs: this.#host.config.accessTokenTtlMs,\n\t\t\t\trefreshTtlMs: this.#host.config.refreshTokenTtlMs,\n\t\t\t\t// Refreshes slide, but never beyond the grant's absolute end (DEC-062).\n\t\t\t\tgrantEndsAt: record.grantCreatedAt + this.#host.config.grantLifetimeMs,\n\t\t\t\tnow,\n\t\t\t},\n\t\t);\n\t\tif (tokens === undefined) {\n\t\t\t// The grant was revoked while this refresh ran (DEC-063).\n\t\t\tthrow invalid(\"the connection was revoked\");\n\t\t}\n\t\tthis.#host.logger.debug(\"oauth.refreshed\", {\n\t\t\taddress: shortAddress(record.addressId),\n\t\t\tclient: hostOf(record.clientId),\n\t\t});\n\t\treturn this.#tokenBody(tokens, record.scopes);\n\t}\n\n\tasync #reuseDetected(record: TokenRecord): Promise<void> {\n\t\tthis.#host.logger.warn(\"oauth.refresh_reuse\", {\n\t\t\taddress: shortAddress(record.addressId),\n\t\t\tclient: hostOf(record.clientId),\n\t\t});\n\t\tawait this.#revokeGrant(record.addressId, record.grantId, \"reuse_detected\");\n\t}\n\n\tasync #revokeGrant(\n\t\taddressId: string,\n\t\tgrantId: string,\n\t\treason: string,\n\t): Promise<void> {\n\t\tconst now = Date.now();\n\t\tconst n = await this.#host.store.revoke(\n\t\t\t{ grantId },\n\t\t\t{ now, keepUntil: now + this.#host.config.grantLifetimeMs },\n\t\t);\n\t\tif (n > 0) this.#host.grantRemoved(addressId, grantId, reason);\n\t}\n\n\t// /revoke\n\n\t/** POST `/revoke` (RFC 7009). */\n\tasync revoke(req: Request, ip: string): Promise<Response> {\n\t\tconst noStore = { \"cache-control\": \"no-store\" };\n\t\ttry {\n\t\t\tif (!this.#tokenPerIp.take(ip)) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t429,\n\t\t\t\t\t\"temporarily_unavailable\",\n\t\t\t\t\t\"too many requests; try again shortly\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst params = await this.#formParams(req);\n\t\t\tconst p = single(params, [\"token\", \"client_id\", \"token_type_hint\"]);\n\t\t\tif (\"duplicate\" in p) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t400,\n\t\t\t\t\t\"invalid_request\",\n\t\t\t\t\t`${p.duplicate} was sent more than once`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst token = p[\"token\"];\n\t\t\tconst clientId = p[\"client_id\"];\n\t\t\tif (token === undefined || clientId === undefined) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t400,\n\t\t\t\t\t\"invalid_request\",\n\t\t\t\t\t\"token and client_id are required\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst record = await this.#host.store.get(hashToken(token));\n\t\t\t// RFC 7009 §2.2: an unknown token is not an error.\n\t\t\tif (record === undefined)\n\t\t\t\treturn new Response(null, {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\theaders: { ...this.#cors(), ...noStore },\n\t\t\t\t});\n\t\t\tif (!constantTimeEqual(clientId, record.clientId)) {\n\t\t\t\tthrow new OAuthError(\n\t\t\t\t\t400,\n\t\t\t\t\t\"invalid_client\",\n\t\t\t\t\t\"the token was issued to another client\",\n\t\t\t\t);\n\t\t\t}\n\t\t\t// The grant is the connection: revoking either token ends it.\n\t\t\tawait this.#revokeGrant(record.addressId, record.grantId, \"revoked\");\n\t\t\tthis.#host.logger.info(\"oauth.revoked\", {\n\t\t\t\taddress: shortAddress(record.addressId),\n\t\t\t\tclient: hostOf(record.clientId),\n\t\t\t\tby: \"client\",\n\t\t\t});\n\t\t\treturn new Response(null, {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: { ...this.#cors(), ...noStore },\n\t\t\t});\n\t\t} catch (error) {\n\t\t\treturn this.#oauthErrorResponse(error, noStore);\n\t\t}\n\t}\n\n\t// Housekeeping\n\n\t/** Drop expired requests; insertion order is expiry order, so stop at the first live one. */\n\t#sweepPending(): void {\n\t\tconst now = Date.now();\n\t\tfor (const p of this.#pending.values()) {\n\t\t\tif (p.expiresAt > now) break;\n\t\t\tthis.#dropPending(p);\n\t\t}\n\t}\n\n\t#sweepCodes(force = false): void {\n\t\tconst now = Date.now();\n\t\t// Keep used codes until they expire, to detect reuse.\n\t\tfor (const [key, c] of this.#codes) {\n\t\t\tif (c.expiresAt <= now) this.#codes.delete(key);\n\t\t}\n\t\tif (force && this.#codes.size >= MAX_CODES) {\n\t\t\tconst drop = this.#codes.size - MAX_CODES + 1;\n\t\t\tfor (const key of [...this.#codes.keys()].slice(0, drop)) {\n\t\t\t\tthis.#codes.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Drop expired state; the relay calls it periodically. */\n\tsweep(): void {\n\t\tthis.#sweepPending();\n\t\tthis.#sweepCodes();\n\t\tconst now = Date.now();\n\t\tthis.#viewsPerIp.sweep(now);\n\t\tthis.#attemptsPerIp.sweep(now);\n\t\tthis.#guessesPerAddressIp.sweep(now);\n\t\tthis.#guessesPerAddress.sweep(now);\n\t\tthis.#tokenPerIp.sweep(now);\n\t}\n}\n",
|
|
12
12
|
"/**\n * In-memory token buckets keyed by IP, address or host (threat model A8).\n * Bounded: when full, the least recently created bucket is dropped, which at\n * worst gives that key a fresh, full bucket.\n */\n\ninterface Bucket {\n\ttokens: number;\n\tupdatedAt: number;\n}\n\nexport interface RateLimitOptions {\n\t/** Burst size: how many requests a fresh key may make at once. */\n\tcapacity: number;\n\t/** Tokens added per second. */\n\trefillPerSecond: number;\n\t/** Most keys kept in memory. */\n\tmaxKeys?: number;\n}\n\nexport class RateLimiter {\n\treadonly #buckets = new Map<string, Bucket>();\n\treadonly #capacity: number;\n\treadonly #refill: number;\n\treadonly #maxKeys: number;\n\n\tconstructor(options: RateLimitOptions) {\n\t\tthis.#capacity = options.capacity;\n\t\tthis.#refill = options.refillPerSecond;\n\t\tthis.#maxKeys = options.maxKeys ?? 10_000;\n\t}\n\n\t/** Take one token for `key`; false when the bucket is empty. */\n\ttake(key: string, now: number = Date.now()): boolean {\n\t\tlet bucket = this.#buckets.get(key);\n\t\tif (bucket === undefined) {\n\t\t\tif (this.#buckets.size >= this.#maxKeys) {\n\t\t\t\tconst oldest = this.#buckets.keys().next().value;\n\t\t\t\tif (oldest !== undefined) this.#buckets.delete(oldest);\n\t\t\t}\n\t\t\tbucket = { tokens: this.#capacity, updatedAt: now };\n\t\t\tthis.#buckets.set(key, bucket);\n\t\t} else {\n\t\t\tconst elapsed = Math.max(0, now - bucket.updatedAt) / 1000;\n\t\t\tbucket.tokens = Math.min(\n\t\t\t\tthis.#capacity,\n\t\t\t\tbucket.tokens + elapsed * this.#refill,\n\t\t\t);\n\t\t\tbucket.updatedAt = now;\n\t\t}\n\t\tif (bucket.tokens < 1) return false;\n\t\tbucket.tokens -= 1;\n\t\treturn true;\n\t}\n\n\t/** Drop buckets that are full again (nothing to remember). */\n\tsweep(now: number = Date.now()): void {\n\t\tfor (const [key, b] of this.#buckets) {\n\t\t\tconst elapsed = Math.max(0, now - b.updatedAt) / 1000;\n\t\t\tif (b.tokens + elapsed * this.#refill >= this.#capacity) {\n\t\t\t\tthis.#buckets.delete(key);\n\t\t\t}\n\t\t}\n\t}\n}\n",
|
|
13
13
|
"import type { TokenKind, TokenRecord, TokenStore } from \"./store/types.ts\";\n\n/** Prefixes make leaked tokens recognisable to secret scanners. */\nconst PREFIX: Record<TokenKind, string> = {\n\taccess: \"tmcp_at_\",\n\trefresh: \"tmcp_rt_\",\n};\n\nfunction random(bytes: number): string {\n\treturn crypto\n\t\t.getRandomValues(new Uint8Array(bytes))\n\t\t.toBase64({ alphabet: \"base64url\", omitPadding: true });\n}\n\n/** A new opaque token with 256 bits of randomness. */\nexport function newToken(kind: TokenKind): string {\n\treturn PREFIX[kind] + random(32);\n}\n\n/** A random identifier with a readable prefix, e.g. `g_…`, `s_…`. */\nexport function newId(prefix: string): string {\n\treturn `${prefix}_${random(12)}`;\n}\n\n/** SHA-256 of a token, base64url without padding: the store key. */\nexport function hashToken(token: string): string {\n\treturn new Bun.CryptoHasher(\"sha256\")\n\t\t.update(token)\n\t\t.digest()\n\t\t.toBase64({ alphabet: \"base64url\", omitPadding: true });\n}\n\n/** The parts of a grant needed to issue tokens for it. */\nexport interface GrantInput {\n\tgrantId?: string;\n\taddressId: string;\n\tclientId: string;\n\tclientName: string;\n\tscopes?: string[];\n\tgrantCreatedAt?: number;\n}\n\n/**\n * Issue an access token for a grant and store its hash, without OAuth. An\n * internal helper for tests that need a token but not the flow; the token\n * endpoint issues through `issueTokenPair`.\n */\nexport async function issueAccessToken(\n\tstore: TokenStore,\n\tgrant: GrantInput,\n\toptions: { ttlMs: number; now?: number },\n): Promise<{ token: string; record: TokenRecord }> {\n\tconst now = options.now ?? Date.now();\n\tconst token = newToken(\"access\");\n\tconst record: TokenRecord = {\n\t\thash: hashToken(token),\n\t\tkind: \"access\",\n\t\tgrantId: grant.grantId ?? newId(\"g\"),\n\t\taddressId: grant.addressId,\n\t\tclientId: grant.clientId,\n\t\tclientName: grant.clientName,\n\t\tscopes: grant.scopes ?? [\"tools\"],\n\t\tgrantCreatedAt: grant.grantCreatedAt ?? now,\n\t\tissuedAt: now,\n\t\texpiresAt: now + options.ttlMs,\n\t};\n\tawait store.put(record);\n\treturn { token, record };\n}\n\n/**\n * A new access token and refresh token for a grant (DEC-029). Neither lives\n * beyond `grantEndsAt` (DEC-062). Returns `undefined` if the store refuses\n * them because the grant was revoked meanwhile (its tombstone, DEC-063).\n */\nexport async function issueTokenPair(\n\tstore: TokenStore,\n\tgrant: Required<Omit<GrantInput, \"scopes\">> & { scopes: string[] },\n\toptions: {\n\t\taccessTtlMs: number;\n\t\trefreshTtlMs: number;\n\t\tgrantEndsAt: number;\n\t\tnow?: number;\n\t},\n): Promise<\n\t{ accessToken: string; refreshToken: string; expiresIn: number } | undefined\n> {\n\tconst now = options.now ?? Date.now();\n\tconst accessToken = newToken(\"access\");\n\tconst refreshToken = newToken(\"refresh\");\n\tconst base = {\n\t\tgrantId: grant.grantId,\n\t\taddressId: grant.addressId,\n\t\tclientId: grant.clientId,\n\t\tclientName: grant.clientName,\n\t\tscopes: grant.scopes,\n\t\tgrantCreatedAt: grant.grantCreatedAt,\n\t\tissuedAt: now,\n\t};\n\tconst accessExpires = Math.min(\n\t\tnow + options.accessTtlMs,\n\t\toptions.grantEndsAt,\n\t);\n\t// The refresh token first: a grant whose access token exists always has\n\t// a way to be listed and revoked. If a revocation lands between the two\n\t// puts, it deletes the first and its tombstone refuses the second.\n\tconst refreshStored = await store.put({\n\t\t...base,\n\t\thash: hashToken(refreshToken),\n\t\tkind: \"refresh\",\n\t\texpiresAt: Math.min(now + options.refreshTtlMs, options.grantEndsAt),\n\t});\n\tif (!refreshStored) return undefined;\n\tconst accessStored = await store.put({\n\t\t...base,\n\t\thash: hashToken(accessToken),\n\t\tkind: \"access\",\n\t\texpiresAt: accessExpires,\n\t});\n\tif (!accessStored) return undefined;\n\treturn {\n\t\taccessToken,\n\t\trefreshToken,\n\t\texpiresIn: Math.max(0, Math.floor((accessExpires - now) / 1000)),\n\t};\n}\n",
|
|
14
14
|
"/**\n * Client ID Metadata Documents (CIMD, draft-ietf-oauth-client-id-metadata-document;\n * MCP 2026-07-28 client registration): the `client_id` is an HTTPS URL, and\n * the relay fetches it to learn the client's name and redirect URIs.\n *\n * The URL is chosen by an unauthenticated party, so the fetch is guarded\n * against SSRF (threat model A3): https only, default port, no credentials,\n * the host resolved first and every address checked to be public, no\n * redirects, 5 s, 64 KiB, `application/json`, results cached and fetches per\n * host rate-limited.\n */\n\nimport { isLoopbackHost, isPublicIp, parseIpv4, parseIpv6 } from \"../ip.ts\";\nimport type { Logger } from \"../log.ts\";\nimport { RateLimiter } from \"../ratelimit.ts\";\n\n/** What the relay needs to know about a client. */\nexport interface ClientMetadata {\n\t/** The client id: the document's URL. */\n\tclientId: string;\n\t/** Self-declared, cleaned and shortened for display. */\n\tname: string;\n\t/** Host of the client id URL: the verified part. */\n\thost: string;\n\tredirectUris: string[];\n}\n\n/** Why a client id was refused; `message` is plain English for the page. */\nexport class ClientMetadataError extends Error {\n\toverride name = \"ClientMetadataError\";\n\treadonly reason: string;\n\tconstructor(reason: string, message: string) {\n\t\tsuper(message);\n\t\tthis.reason = reason;\n\t}\n}\n\n/**\n * Test-only relaxations (never from configuration): loopback hosts, any port,\n * `http:`, and an extra CA for a self-signed test server.\n */\nexport interface CimdTestMode {\n\tca?: string;\n}\n\nexport interface ClientMetadataFetcherOptions {\n\t/** Accepted client id hosts; empty = any. */\n\tallowedHosts?: readonly string[];\n\tlogger?: Logger;\n\ttimeoutMs?: number;\n\tmaxBytes?: number;\n\t/** Resolve a host name to its addresses (tests replace it). */\n\tlookup?: (hostname: string) => Promise<string[]>;\n\tfetch?: typeof fetch;\n\ttestMode?: CimdTestMode;\n\tnow?: () => number;\n}\n\nconst MAX_CLIENT_ID_LENGTH = 2048;\nconst MAX_NAME_LENGTH = 64;\nconst MAX_REDIRECT_URIS = 20;\nconst MIN_CACHE_MS = 5 * 60_000;\nconst DEFAULT_CACHE_MS = 60 * 60_000;\nconst MAX_CACHE_MS = 24 * 60 * 60_000;\nconst MAX_CACHE_ENTRIES = 1000;\n\nasync function defaultLookup(hostname: string): Promise<string[]> {\n\tconst records = await Bun.dns.lookup(hostname, {});\n\treturn records.map((r) => r.address);\n}\n\n/**\n * Invisible characters that are not format characters (`Cf`): Hangul and\n * other fillers, the braille blank, combining grapheme joiner.\n */\nconst INVISIBLE = /[\\u034F\\u115F\\u1160\\u17B4\\u17B5\\u2800\\u3164\\uFFA0]/gu;\n\n/**\n * Clean a self-declared name for display: control and line/paragraph\n * separators become spaces; format characters (`Cf`: zero-width, bidi,\n * word joiner, BOM, soft hyphen, …) and other invisible characters are\n * removed; whitespace collapses; at most 64 characters (DEC-065).\n */\nexport function displayName(raw: string): string {\n\tlet cleaned = raw\n\t\t.normalize(\"NFC\")\n\t\t.replace(/[\\p{Cc}\\p{Zl}\\p{Zp}]/gu, \" \")\n\t\t.replace(/\\p{Cf}/gu, \"\")\n\t\t.replace(INVISIBLE, \"\");\n\tcleaned = cleaned.replace(/\\s+/g, \" \").trim();\n\tconst chars = [...cleaned];\n\treturn chars.length > MAX_NAME_LENGTH\n\t\t? `${chars.slice(0, MAX_NAME_LENGTH - 1).join(\"\")}…`\n\t\t: cleaned;\n}\n\n/** Seconds of `max-age` in a Cache-Control header, or a marker. */\nfunction cacheMs(header: string | null): number {\n\tif (header === null) return DEFAULT_CACHE_MS;\n\tconst directives = header\n\t\t.toLowerCase()\n\t\t.split(\",\")\n\t\t.map((d) => d.trim());\n\tif (directives.includes(\"no-store\") || directives.includes(\"no-cache\")) {\n\t\treturn MIN_CACHE_MS;\n\t}\n\tconst maxAge = directives\n\t\t.map((d) => /^max-age=(\\d+)$/.exec(d)?.[1])\n\t\t.find((v) => v !== undefined);\n\tif (maxAge === undefined) return DEFAULT_CACHE_MS;\n\treturn Math.min(MAX_CACHE_MS, Math.max(MIN_CACHE_MS, Number(maxAge) * 1000));\n}\n\nfunction isIpLiteral(hostname: string): boolean {\n\tconst h = hostname.replace(/^\\[|\\]$/g, \"\");\n\treturn parseIpv4(h) !== undefined || parseIpv6(h) !== undefined;\n}\n\n/** Fetches, validates and caches Client ID Metadata Documents. */\nexport class ClientMetadataFetcher {\n\treadonly #cache = new Map<string, { meta: ClientMetadata; until: number }>();\n\treadonly #perHost = new RateLimiter({ capacity: 5, refillPerSecond: 0.2 });\n\t/** All fetches together: many attacker-owned hosts cannot add up (DEC-061). */\n\treadonly #global = new RateLimiter({ capacity: 30, refillPerSecond: 1 });\n\treadonly #allowedHosts: readonly string[];\n\treadonly #logger: Logger | undefined;\n\treadonly #timeoutMs: number;\n\treadonly #maxBytes: number;\n\treadonly #lookup: (hostname: string) => Promise<string[]>;\n\treadonly #fetch: typeof fetch;\n\treadonly #testMode: CimdTestMode | undefined;\n\treadonly #now: () => number;\n\n\tconstructor(options: ClientMetadataFetcherOptions = {}) {\n\t\tthis.#allowedHosts = options.allowedHosts ?? [];\n\t\tthis.#logger = options.logger;\n\t\tthis.#timeoutMs = options.timeoutMs ?? 5000;\n\t\tthis.#maxBytes = options.maxBytes ?? 65_536;\n\t\tthis.#lookup = options.lookup ?? defaultLookup;\n\t\tthis.#fetch = options.fetch ?? fetch;\n\t\tthis.#testMode = options.testMode;\n\t\tthis.#now = options.now ?? Date.now;\n\t}\n\n\t/** The client's metadata, from the cache or freshly fetched. Throws `ClientMetadataError`. */\n\tasync get(clientId: string): Promise<ClientMetadata> {\n\t\tconst url = this.#checkUrl(clientId);\n\t\tconst now = this.#now();\n\t\tconst cached = this.#cache.get(clientId);\n\t\tif (cached !== undefined && cached.until > now) return cached.meta;\n\t\tif (!this.#perHost.take(url.host, now)) {\n\t\t\tthrow new ClientMetadataError(\n\t\t\t\t\"rate_limited\",\n\t\t\t\t\"Too many requests for this AI app's details. Try again in a minute.\",\n\t\t\t);\n\t\t}\n\t\tif (!this.#global.take(\"all\", now)) {\n\t\t\tthrow new ClientMetadataError(\n\t\t\t\t\"rate_limited\",\n\t\t\t\t\"The relay is busy. Try again in a minute.\",\n\t\t\t);\n\t\t}\n\t\tconst address = await this.#vettedAddress(url);\n\t\tconst { meta, ttlMs } = await this.#fetchDocument(url, clientId, address);\n\t\tif (this.#cache.size >= MAX_CACHE_ENTRIES) {\n\t\t\tconst oldest = this.#cache.keys().next().value;\n\t\t\tif (oldest !== undefined) this.#cache.delete(oldest);\n\t\t}\n\t\tthis.#cache.delete(clientId);\n\t\tthis.#cache.set(clientId, { meta, until: now + ttlMs });\n\t\treturn meta;\n\t}\n\n\t/** The URL rules of the CIMD draft plus our SSRF rules, before any network use. */\n\t#checkUrl(clientId: string): URL {\n\t\tconst refuse = (message: string) =>\n\t\t\tnew ClientMetadataError(\"invalid_client_id\", message);\n\t\tif (clientId.length === 0 || clientId.length > MAX_CLIENT_ID_LENGTH) {\n\t\t\tthrow refuse(\"The AI app's client_id is missing or too long.\");\n\t\t}\n\t\tlet url: URL;\n\t\ttry {\n\t\t\turl = new URL(clientId);\n\t\t} catch {\n\t\t\tthrow refuse(\"The AI app's client_id is not a URL.\");\n\t\t}\n\t\tconst test = this.#testMode !== undefined;\n\t\tconst scheme =\n\t\t\turl.protocol === \"https:\" || (test && url.protocol === \"http:\");\n\t\tif (!scheme) {\n\t\t\tthrow refuse(\"The AI app's client_id must be an https:// URL.\");\n\t\t}\n\t\t// Canonical form only: this rejects dot segments, fragments' oddities,\n\t\t// an explicit default port, upper-case hosts and other aliases.\n\t\tif (url.href !== clientId) {\n\t\t\tthrow refuse(\"The AI app's client_id is not a canonical URL.\");\n\t\t}\n\t\tif (url.username !== \"\" || url.password !== \"\" || url.hash !== \"\") {\n\t\t\tthrow refuse(\n\t\t\t\t\"The AI app's client_id must not contain credentials or a fragment.\",\n\t\t\t);\n\t\t}\n\t\tif (url.pathname === \"/\" || url.pathname === \"\") {\n\t\t\tthrow refuse(\"The AI app's client_id must have a path.\");\n\t\t}\n\t\tif (url.port !== \"\" && !test) {\n\t\t\tthrow refuse(\"The AI app's client_id must use the default port.\");\n\t\t}\n\t\tif (\n\t\t\tthis.#allowedHosts.length > 0 &&\n\t\t\t!this.#allowedHosts.includes(url.host)\n\t\t) {\n\t\t\tthrow new ClientMetadataError(\n\t\t\t\t\"host_not_allowed\",\n\t\t\t\t`This relay does not accept AI apps from ${url.host}.`,\n\t\t\t);\n\t\t}\n\t\tif (isIpLiteral(url.hostname) && !this.#addressAllowed(url.hostname)) {\n\t\t\tthrow this.#notLoaded(\"private_address\", url);\n\t\t}\n\t\treturn url;\n\t}\n\n\t#addressAllowed(address: string): boolean {\n\t\tif (isPublicIp(address)) return true;\n\t\treturn this.#testMode !== undefined && isLoopbackHost(address);\n\t}\n\n\t/**\n\t * One fixed message for every failure from resolving to parsing, so the\n\t * page tells nothing about what answered (threat model A3, DEC-066). The\n\t * reason goes to the log.\n\t */\n\t#notLoaded(reason: string, url: URL, detail = reason): ClientMetadataError {\n\t\tthis.#logger?.info(\"oauth.cimd_failed\", { host: url.host, reason: detail });\n\t\treturn new ClientMetadataError(\n\t\t\treason,\n\t\t\t`The AI app's details could not be loaded from ${url.host}.`,\n\t\t);\n\t}\n\n\t/**\n\t * Resolve the host, refuse it if any address is not public, and return the\n\t * address to connect to (IPv4 first). The fetch is pinned to it, so a DNS\n\t * answer that changes between check and connect is never used.\n\t */\n\tasync #vettedAddress(url: URL): Promise<string> {\n\t\tconst hostname = url.hostname.replace(/^\\[|\\]$/g, \"\");\n\t\tif (isIpLiteral(hostname)) return hostname; // checked in #checkUrl\n\t\tlet addresses: string[];\n\t\ttry {\n\t\t\taddresses = await this.#lookup(hostname);\n\t\t} catch {\n\t\t\tthrow this.#notLoaded(\"unresolvable\", url);\n\t\t}\n\t\tif (\n\t\t\taddresses.length === 0 ||\n\t\t\t!addresses.every((a) => this.#addressAllowed(a))\n\t\t) {\n\t\t\tthrow this.#notLoaded(\"private_address\", url);\n\t\t}\n\t\treturn (\n\t\t\taddresses.find((a) => parseIpv4(a) !== undefined) ?? addresses[0] ?? \"\"\n\t\t);\n\t}\n\n\tasync #fetchDocument(\n\t\turl: URL,\n\t\tclientId: string,\n\t\taddress: string,\n\t): Promise<{ meta: ClientMetadata; ttlMs: number }> {\n\t\tconst fail = (detail: string) =>\n\t\t\tthis.#notLoaded(\"fetch_failed\", url, detail);\n\t\t// Connect to the vetted address; Host and the TLS server name stay the\n\t\t// original host, so the certificate is checked against it.\n\t\tconst pinned = new URL(clientId);\n\t\tpinned.hostname = address.includes(\":\") ? `[${address}]` : address;\n\t\tconst hostname = url.hostname.replace(/^\\[|\\]$/g, \"\");\n\t\tconst tls =\n\t\t\turl.protocol === \"https:\"\n\t\t\t\t? {\n\t\t\t\t\t\ttls: {\n\t\t\t\t\t\t\t...(isIpLiteral(hostname) ? {} : { serverName: hostname }),\n\t\t\t\t\t\t\t...(this.#testMode?.ca === undefined\n\t\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t\t: { ca: this.#testMode.ca }),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: {};\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await this.#fetch(pinned.href, {\n\t\t\t\tmethod: \"GET\",\n\t\t\t\tredirect: \"manual\",\n\t\t\t\theaders: { accept: \"application/json\", host: url.host },\n\t\t\t\tsignal: AbortSignal.timeout(this.#timeoutMs),\n\t\t\t\t...tls,\n\t\t\t} as RequestInit);\n\t\t} catch (error) {\n\t\t\tthrow fail(\n\t\t\t\t`fetch_failed:${error instanceof Error ? error.name : \"unknown\"}`,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tif (response.status !== 200) throw fail(`status_${response.status}`);\n\t\t\tconst type = (response.headers.get(\"content-type\") ?? \"\")\n\t\t\t\t.split(\";\")[0]\n\t\t\t\t?.trim()\n\t\t\t\t.toLowerCase();\n\t\t\tif (type !== \"application/json\") throw fail(\"not_json\");\n\t\t\tconst text = await this.#readLimited(response, url);\n\t\t\tlet doc: unknown;\n\t\t\ttry {\n\t\t\t\tdoc = JSON.parse(text);\n\t\t\t} catch {\n\t\t\t\tthrow fail(\"bad_json\");\n\t\t\t}\n\t\t\tconst meta = validateDocument(doc, clientId, url);\n\t\t\treturn { meta, ttlMs: cacheMs(response.headers.get(\"cache-control\")) };\n\t\t} finally {\n\t\t\tif (!response.bodyUsed) response.body?.cancel().catch(() => {});\n\t\t}\n\t}\n\n\tasync #readLimited(response: Response, url: URL): Promise<string> {\n\t\tconst tooLarge = () => this.#notLoaded(\"too_large\", url);\n\t\tconst length = Number(response.headers.get(\"content-length\") ?? \"0\");\n\t\tif (length > this.#maxBytes) throw tooLarge();\n\t\tconst reader = response.body?.getReader();\n\t\tif (reader === undefined) return \"\";\n\t\tconst chunks: Uint8Array[] = [];\n\t\tlet total = 0;\n\t\tfor (;;) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\ttotal += value.byteLength;\n\t\t\tif (total > this.#maxBytes) {\n\t\t\t\tawait reader.cancel().catch(() => {});\n\t\t\t\tthrow tooLarge();\n\t\t\t}\n\t\t\tchunks.push(value);\n\t\t}\n\t\ttry {\n\t\t\treturn new TextDecoder(\"utf-8\", { fatal: true }).decode(\n\t\t\t\tBuffer.concat(chunks),\n\t\t\t);\n\t\t} catch {\n\t\t\tthrow this.#notLoaded(\"fetch_failed\", url, \"bad_utf8\");\n\t\t}\n\t}\n}\n\n/** Check a fetched document against the CIMD rules and what the relay supports. */\nexport function validateDocument(\n\tdoc: unknown,\n\tclientId: string,\n\turl: URL,\n): ClientMetadata {\n\tconst invalid = (message: string) =>\n\t\tnew ClientMetadataError(\"invalid_metadata\", message);\n\tif (typeof doc !== \"object\" || doc === null || Array.isArray(doc)) {\n\t\tthrow invalid(\"The AI app's details are not a JSON object.\");\n\t}\n\tconst d = doc as Record<string, unknown>;\n\tif (d[\"client_id\"] !== clientId) {\n\t\tthrow invalid(\"The AI app's details name a different client_id.\");\n\t}\n\tif (\n\t\td[\"client_secret\"] !== undefined ||\n\t\td[\"client_secret_expires_at\"] !== undefined\n\t) {\n\t\tthrow invalid(\"The AI app's details must not contain a client secret.\");\n\t}\n\tconst name = d[\"client_name\"];\n\tif (typeof name !== \"string\" || displayName(name) === \"\") {\n\t\tthrow invalid(\"The AI app's details have no client_name.\");\n\t}\n\t// \"Claude (claude.ai)\" from evil.example would read like a verified host.\n\tif (/\\(\\s*[^()\\s]*[a-z0-9-]\\.[a-z]{2,}[^()]*\\)/i.test(displayName(name))) {\n\t\tthrow invalid(\n\t\t\t\"The AI app's name contains a web address in parentheses, which this relay does not show.\",\n\t\t);\n\t}\n\tconst uris = d[\"redirect_uris\"];\n\tif (\n\t\t!Array.isArray(uris) ||\n\t\turis.length === 0 ||\n\t\turis.length > MAX_REDIRECT_URIS ||\n\t\t!uris.every((u) => typeof u === \"string\" && isRedirectUri(u))\n\t) {\n\t\tthrow invalid(\"The AI app's details have no valid redirect_uris.\");\n\t}\n\tconst method = d[\"token_endpoint_auth_method\"];\n\tif (method !== undefined && method !== \"none\") {\n\t\tthrow invalid(\n\t\t\t'The AI app must use token_endpoint_auth_method \"none\" with this relay.',\n\t\t);\n\t}\n\tconst grants = d[\"grant_types\"];\n\tif (\n\t\tgrants !== undefined &&\n\t\t(!Array.isArray(grants) || !grants.includes(\"authorization_code\"))\n\t) {\n\t\tthrow invalid(\n\t\t\t\"The AI app's details do not allow the authorization code grant.\",\n\t\t);\n\t}\n\tconst responses = d[\"response_types\"];\n\tif (\n\t\tresponses !== undefined &&\n\t\t(!Array.isArray(responses) || !responses.includes(\"code\"))\n\t) {\n\t\tthrow invalid('The AI app\\'s details do not allow response type \"code\".');\n\t}\n\treturn {\n\t\tclientId,\n\t\tname: displayName(name),\n\t\thost: url.host,\n\t\tredirectUris: uris as string[],\n\t};\n}\n\n/** A private-use URI scheme in reverse-domain form (RFC 8252 §7.1), e.g. `com.example.app:`. */\nconst PRIVATE_USE_SCHEME = /^[a-z][a-z0-9+-]*(\\.[a-z0-9+-]+)+:$/;\n\n/**\n * A redirect URI the relay accepts (DEC-067): absolute, no fragment or\n * credentials, and `https:`; `http:` only for loopback hosts (RFC 8252 §7.3);\n * or a reverse-domain private-use scheme for native apps (RFC 8252 §7.1).\n * Everything else (`file:`, `blob:`, `data:`, `javascript:`, plain `http:`,\n * one-word custom schemes) is refused.\n */\nexport function isRedirectUri(value: string): boolean {\n\tif (value.length > 2048 || value.includes(\"#\")) return false;\n\tlet u: URL;\n\ttry {\n\t\tu = new URL(value);\n\t} catch {\n\t\treturn false;\n\t}\n\tif (u.username !== \"\" || u.password !== \"\") return false;\n\tif (u.protocol === \"https:\") return u.hostname !== \"\";\n\tif (u.protocol === \"http:\") return LOOPBACK_REDIRECT_HOSTS.has(u.hostname);\n\treturn PRIVATE_USE_SCHEME.test(u.protocol);\n}\n\nconst LOOPBACK_REDIRECT_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"[::1]\"]);\n\n/**\n * Whether a requested redirect URI matches a registered one: exact string\n * equality, except that for an `http:` loopback redirect the port is ignored\n * (RFC 8252 §7.3; OAuth 2.1 §8.4.2). Host, path and query must still match.\n */\nexport function redirectUriMatches(\n\trequested: string,\n\tregistered: string,\n): boolean {\n\tif (requested === registered) return true;\n\tlet a: URL;\n\tlet b: URL;\n\ttry {\n\t\ta = new URL(requested);\n\t\tb = new URL(registered);\n\t} catch {\n\t\treturn false;\n\t}\n\tif (a.protocol !== \"http:\" || b.protocol !== \"http:\") return false;\n\tif (!LOOPBACK_REDIRECT_HOSTS.has(b.hostname) || a.hostname !== b.hostname) {\n\t\treturn false;\n\t}\n\t// The requested URI must be in canonical form, so the parser cannot\n\t// have changed what the comparison sees (dot segments, case, …).\n\tif (\n\t\ta.href !== requested ||\n\t\ta.username !== \"\" ||\n\t\ta.password !== \"\" ||\n\t\ta.hash !== \"\"\n\t) {\n\t\treturn false;\n\t}\n\ta.port = \"\";\n\tb.port = \"\";\n\treturn a.href === b.href;\n}\n",
|
|
15
|
-
"/**\n * Server-rendered HTML for `/authorize` (threat model A7): every value is\n * escaped, the page has no scripts, and its headers forbid framing, inline\n * code and foreign form targets.\n */\n\nconst ESCAPES: Record<string, string> = {\n\t\"&\": \"&\",\n\t\"<\": \"<\",\n\t\">\": \">\",\n\t'\"': \""\",\n\t\"'\": \"'\",\n};\n\n/** Escape text for HTML element content and quoted attribute values. */\nexport function escapeHtml(text: string): string {\n\treturn text.replace(/[&<>\"']/g, (c) => ESCAPES[c] ?? c);\n}\n\n/** The stylesheet at `/authorize.css` (`style-src 'self'`). */\nexport const AUTHORIZE_CSS = `:root { color-scheme: light dark; --accent: #1d4ed8; --error: #b91c1c; }\n@media (prefers-color-scheme: dark) { :root { --accent: #93b4ff; --error: #fca5a5; } }\n* { box-sizing: border-box; }\nbody { margin: 0; font: 1rem/1.5 system-ui, -apple-system, \"Segoe UI\", sans-serif; background: Canvas; color: CanvasText; }\nmain { max-width: 34rem; margin: 3rem auto; padding: 0 1rem; }\nh1 { font-size: 1.5rem; line-height: 1.25; margin: 0 0 1rem; }\np { margin: 0 0 1rem; }\ncode, .origin { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; overflow-wrap: anywhere; }\n.help { color: GrayText; font-size: 0.9rem; }\n.error { color: var(--error); font-weight: 600; }\nlabel { display: block; font-weight: 600; margin-bottom: 0.25rem; }\ninput[type=\"text\"] { font: 1.5rem/1.2 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.2em; width: 10ch; padding: 0.4rem 0.5rem; border: 2px solid GrayText; border-radius: 0.4rem; background: Field; color: FieldText; }\ninput[type=\"text\"]:focus-visible, button:focus-visible, a:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }\n.actions { display: flex; gap: 0.75rem; flex-wrap: wrap; margin: 1.5rem 0 1.25rem; }\nbutton, .button { font: inherit; padding: 0.5rem 1.25rem; border-radius: 0.4rem; border: 2px solid var(--accent); cursor: pointer; text-decoration: none; display: inline-block; }\nbutton.primary, .button.primary { background: var(--accent); color: Canvas; }\nbutton.secondary, .button:not(.primary) { background: transparent; color: var(--accent); }\nfooter { margin-top: 2.5rem; font-size: 0.85rem; color: GrayText; }\n`;\n\n/** Security headers of every `/authorize` response. */\nexport function pageHeaders(formTargets: readonly string[] = []): Headers {\n\t// Chrome applies form-action to the redirect after a POST, so the client's\n\t// redirect origin must be allowed explicitly.\n\tconst formAction = [\"'self'\", ...formTargets].join(\" \");\n\treturn new Headers({\n\t\t\"content-type\": \"text/html; charset=utf-8\",\n\t\t\"content-security-policy\": `default-src 'none'; style-src 'self'; img-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action ${formAction}`,\n\t\t\"x-frame-options\": \"DENY\",\n\t\t\"x-content-type-options\": \"nosniff\",\n\t\t// Not no-referrer: browsers then send `Origin: null` on the form post,\n\t\t// which the origin check must refuse. same-origin still sends nothing\n\t\t// to the client's redirect.\n\t\t\"referrer-policy\": \"same-origin\",\n\t\t\"cache-control\": \"no-store\",\n\t});\n}\n\n/** A complete page; `body` must already be escaped. */\nexport function renderPage(title: string, body: string): string {\n\treturn `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta name=\"robots\" content=\"noindex\">\n<title>${escapeHtml(title)}</title>\n<link rel=\"stylesheet\" href=\"/authorize.css\">\n</head>\n<body>\n<main>\n${body}\n<footer>tab-mcp relay. It passes requests between AI
|
|
16
|
-
"/**\n * Pairing (DEC-028, DEC-042): the step at `/authorize` that proves the browser\n * belongs to the tab's user. The authorization server only knows the\n * `PairingMethod` interface; which method a session uses comes from its site\n * (DEC-045). Today's only method is the 6-digit code shown in the tab; the\n * planned identity binding (kb/design/identity-binding.md) is the next.\n */\n\nimport { timingSafeEqual } from \"node:crypto\";\nimport type { PairingKind } from \"../config.ts\";\n\n/** What a pairing method sees of a tab session. */\nexport interface PairingTarget {\n\t/** The code state of the session (used by the code method). */\n\treadonly codes: PairingCodes;\n}\n\nexport type PairingResult =\n\t| { ok: true }\n\t| {\n\t\t\tok: false;\n\t\t\t/** Plain English for the page (plain text; the page escapes it). */\n\t\t\tmessage: string;\n\t\t\t/** A short reason for the log. */\n\t\t\treason: string;\n\t };\n\n/**\n * A way to pair a browser at `/authorize` with an address. The authorization\n * server renders `render()` inside its form (CSRF token, buttons and the\n * request id are its own) and passes the submitted form to `check()`.\n */\nexport interface PairingMethod {\n\treadonly kind: PairingKind;\n\t/** HTML of the method's step (escaped by the method). */\n\trender(target: PairingTarget): string;\n\t/**\n\t * Check the submitted form fields. Call `admit()` right before judging an\n\t * answer that could be right (a real guess); if it returns false, refuse\n\t * with reason `rate_limited` without judging. Malformed input and a state\n\t * that cannot succeed are answered without calling it (DEC-061).\n\t */\n\tcheck(\n\t\ttarget: PairingTarget,\n\t\tform: URLSearchParams,\n\t\tadmit: () => boolean,\n\t): PairingResult | Promise<PairingResult>;\n}\n\n/** Code lifetime and attempts (DEC-028). */\nexport const PAIRING_CODE_TTL_MS = 120_000;\nexport const PAIRING_MAX_ATTEMPTS = 5;\n\nexport type CodeCheck =\n\t| \"ok\"\n\t| \"limited\"\n\t| \"wrong\"\n\t| \"expired\"\n\t| \"locked\"\n\t| \"inactive\"\n\t| \"malformed\";\n\n/** Six uniformly distributed digits. */\nexport function newPairingCode(): string {\n\t// 4 294 000 000 is the largest multiple of 10^6 below 2^32: rejecting the\n\t// values above it keeps every code equally likely.\n\tconst buffer = new Uint32Array(1);\n\tfor (;;) {\n\t\tcrypto.getRandomValues(buffer);\n\t\tconst n = buffer[0] ?? 0;\n\t\tif (n < 4_294_000_000) return String(n % 1_000_000).padStart(6, \"0\");\n\t}\n}\n\nfunction sameCode(a: string, b: string): boolean {\n\tconst x = Buffer.from(a);\n\tconst y = Buffer.from(b);\n\treturn x.length === y.length && timingSafeEqual(x, y);\n}\n\n/**\n * The pairing codes of one tab session: on while the tab's dialog is open\n * (`pairing.start` … `pairing.stop`); a fresh code after expiry, after use and\n * after too many wrong attempts. Codes are never logged.\n */\nexport class PairingCodes {\n\treadonly #send: (code: string, expiresAt: number) => void;\n\treadonly #ttlMs: number;\n\treadonly #maxAttempts: number;\n\t#current: { code: string; expiresAt: number; attempts: number } | undefined;\n\t#previous: string | undefined;\n\t#timer: Timer | undefined;\n\n\tconstructor(\n\t\tsend: (code: string, expiresAt: number) => void,\n\t\toptions: { ttlMs?: number; maxAttempts?: number } = {},\n\t) {\n\t\tthis.#send = send;\n\t\tthis.#ttlMs = options.ttlMs ?? PAIRING_CODE_TTL_MS;\n\t\tthis.#maxAttempts = options.maxAttempts ?? PAIRING_MAX_ATTEMPTS;\n\t}\n\n\t/** Whether the tab is showing codes. */\n\tget active(): boolean {\n\t\treturn this.#current !== undefined;\n\t}\n\n\t/** Attempts left for the current code. */\n\tget attemptsLeft(): number {\n\t\treturn this.#current === undefined\n\t\t\t? 0\n\t\t\t: this.#maxAttempts - this.#current.attempts;\n\t}\n\n\tstart(): void {\n\t\tif (this.#current !== undefined) {\n\t\t\t// Already on (e.g. a second dialog): show the same code again.\n\t\t\tthis.#send(this.#current.code, this.#current.expiresAt);\n\t\t\treturn;\n\t\t}\n\t\tthis.#issue();\n\t}\n\n\tstop(): void {\n\t\tclearTimeout(this.#timer);\n\t\tthis.#timer = undefined;\n\t\tthis.#current = undefined;\n\t\tthis.#previous = undefined;\n\t}\n\n\t/**\n\t * Check a typed code; a correct one is used up and replaced. `admit` is\n\t * asked only for a well-formed code while a code is active.\n\t */\n\tcheck(\n\t\tinput: string,\n\t\tnow: number = Date.now(),\n\t\tadmit: () => boolean = () => true,\n\t): CodeCheck {\n\t\tconst current = this.#current;\n\t\tif (current === undefined) return \"inactive\";\n\t\tconst typed = input.replace(/[\\s-]/g, \"\");\n\t\tif (!/^\\d{6}$/.test(typed)) return \"malformed\";\n\t\tif (!admit()) return \"limited\";\n\t\tif (now >= current.expiresAt) {\n\t\t\tthis.#previous = current.code;\n\t\t\tthis.#issue();\n\t\t\treturn \"expired\";\n\t\t}\n\t\tif (sameCode(typed, current.code)) {\n\t\t\tthis.#previous = undefined;\n\t\t\tthis.#issue();\n\t\t\treturn \"ok\";\n\t\t}\n\t\tcurrent.attempts++;\n\t\tconst expired =\n\t\t\tthis.#previous !== undefined && sameCode(typed, this.#previous);\n\t\tif (current.attempts >= this.#maxAttempts) {\n\t\t\tthis.#previous = undefined;\n\t\t\tthis.#issue();\n\t\t\treturn \"locked\";\n\t\t}\n\t\treturn expired ? \"expired\" : \"wrong\";\n\t}\n\n\t#issue(): void {\n\t\tclearTimeout(this.#timer);\n\t\tconst expiresAt = Date.now() + this.#ttlMs;\n\t\tthis.#current = { code: newPairingCode(), expiresAt, attempts: 0 };\n\t\tthis.#timer = setTimeout(() => {\n\t\t\tif (this.#current === undefined) return;\n\t\t\tthis.#previous = this.#current.code;\n\t\t\tthis.#issue();\n\t\t}, this.#ttlMs);\n\t\tthis.#send(this.#current.code, expiresAt);\n\t}\n}\n\nconst MESSAGES: Record<Exclude<CodeCheck, \"ok\">, string> = {\n\twrong:\n\t\t\"That code is not right. Check the code shown in the page and try again.\",\n\texpired:\n\t\t\"That code has expired. The page now shows a new code: enter that one.\",\n\tlocked:\n\t\t\"Too many wrong codes. The page now shows a new code: enter that one.\",\n\tinactive:\n\t\t\"The page is not showing a code right now. In the page, open “Connect your AI
|
|
15
|
+
"/**\n * Server-rendered HTML for `/authorize` (threat model A7): every value is\n * escaped, the page has no scripts, and its headers forbid framing, inline\n * code and foreign form targets.\n */\n\nconst ESCAPES: Record<string, string> = {\n\t\"&\": \"&\",\n\t\"<\": \"<\",\n\t\">\": \">\",\n\t'\"': \""\",\n\t\"'\": \"'\",\n};\n\n/** Escape text for HTML element content and quoted attribute values. */\nexport function escapeHtml(text: string): string {\n\treturn text.replace(/[&<>\"']/g, (c) => ESCAPES[c] ?? c);\n}\n\n/** The stylesheet at `/authorize.css` (`style-src 'self'`). */\nexport const AUTHORIZE_CSS = `:root { color-scheme: light dark; --accent: #1d4ed8; --error: #b91c1c; }\n@media (prefers-color-scheme: dark) { :root { --accent: #93b4ff; --error: #fca5a5; } }\n* { box-sizing: border-box; }\nbody { margin: 0; font: 1rem/1.5 system-ui, -apple-system, \"Segoe UI\", sans-serif; background: Canvas; color: CanvasText; }\nmain { max-width: 34rem; margin: 3rem auto; padding: 0 1rem; }\nh1 { font-size: 1.5rem; line-height: 1.25; margin: 0 0 1rem; }\np { margin: 0 0 1rem; }\ncode, .origin { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; overflow-wrap: anywhere; }\n.help { color: GrayText; font-size: 0.9rem; }\n.error { color: var(--error); font-weight: 600; }\nlabel { display: block; font-weight: 600; margin-bottom: 0.25rem; }\ninput[type=\"text\"] { font: 1.5rem/1.2 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.2em; width: 10ch; padding: 0.4rem 0.5rem; border: 2px solid GrayText; border-radius: 0.4rem; background: Field; color: FieldText; }\ninput[type=\"text\"]:focus-visible, button:focus-visible, a:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }\n.actions { display: flex; gap: 0.75rem; flex-wrap: wrap; margin: 1.5rem 0 1.25rem; }\nbutton, .button { font: inherit; padding: 0.5rem 1.25rem; border-radius: 0.4rem; border: 2px solid var(--accent); cursor: pointer; text-decoration: none; display: inline-block; }\nbutton.primary, .button.primary { background: var(--accent); color: Canvas; }\nbutton.secondary, .button:not(.primary) { background: transparent; color: var(--accent); }\nfooter { margin-top: 2.5rem; font-size: 0.85rem; color: GrayText; }\n`;\n\n/** Security headers of every `/authorize` response. */\nexport function pageHeaders(formTargets: readonly string[] = []): Headers {\n\t// Chrome applies form-action to the redirect after a POST, so the client's\n\t// redirect origin must be allowed explicitly.\n\tconst formAction = [\"'self'\", ...formTargets].join(\" \");\n\treturn new Headers({\n\t\t\"content-type\": \"text/html; charset=utf-8\",\n\t\t\"content-security-policy\": `default-src 'none'; style-src 'self'; img-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action ${formAction}`,\n\t\t\"x-frame-options\": \"DENY\",\n\t\t\"x-content-type-options\": \"nosniff\",\n\t\t// Not no-referrer: browsers then send `Origin: null` on the form post,\n\t\t// which the origin check must refuse. same-origin still sends nothing\n\t\t// to the client's redirect.\n\t\t\"referrer-policy\": \"same-origin\",\n\t\t\"cache-control\": \"no-store\",\n\t});\n}\n\n/** A complete page; `body` must already be escaped. */\nexport function renderPage(title: string, body: string): string {\n\treturn `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta name=\"robots\" content=\"noindex\">\n<title>${escapeHtml(title)}</title>\n<link rel=\"stylesheet\" href=\"/authorize.css\">\n</head>\n<body>\n<main>\n${body}\n<footer>tab-mcp relay. It passes requests between AI apps and web pages and does not store their contents.</footer>\n</main>\n</body>\n</html>`;\n}\n",
|
|
16
|
+
"/**\n * Pairing (DEC-028, DEC-042): the step at `/authorize` that proves the browser\n * belongs to the tab's user. The authorization server only knows the\n * `PairingMethod` interface; which method a session uses comes from its site\n * (DEC-045). Today's only method is the 6-digit code shown in the tab; the\n * planned identity binding (kb/design/identity-binding.md) is the next.\n */\n\nimport { timingSafeEqual } from \"node:crypto\";\nimport type { PairingKind } from \"../config.ts\";\n\n/** What a pairing method sees of a tab session. */\nexport interface PairingTarget {\n\t/** The code state of the session (used by the code method). */\n\treadonly codes: PairingCodes;\n}\n\nexport type PairingResult =\n\t| { ok: true }\n\t| {\n\t\t\tok: false;\n\t\t\t/** Plain English for the page (plain text; the page escapes it). */\n\t\t\tmessage: string;\n\t\t\t/** A short reason for the log. */\n\t\t\treason: string;\n\t };\n\n/**\n * A way to pair a browser at `/authorize` with an address. The authorization\n * server renders `render()` inside its form (CSRF token, buttons and the\n * request id are its own) and passes the submitted form to `check()`.\n */\nexport interface PairingMethod {\n\treadonly kind: PairingKind;\n\t/** HTML of the method's step (escaped by the method). */\n\trender(target: PairingTarget): string;\n\t/**\n\t * Check the submitted form fields. Call `admit()` right before judging an\n\t * answer that could be right (a real guess); if it returns false, refuse\n\t * with reason `rate_limited` without judging. Malformed input and a state\n\t * that cannot succeed are answered without calling it (DEC-061).\n\t */\n\tcheck(\n\t\ttarget: PairingTarget,\n\t\tform: URLSearchParams,\n\t\tadmit: () => boolean,\n\t): PairingResult | Promise<PairingResult>;\n}\n\n/** Code lifetime and attempts (DEC-028). */\nexport const PAIRING_CODE_TTL_MS = 120_000;\nexport const PAIRING_MAX_ATTEMPTS = 5;\n\nexport type CodeCheck =\n\t| \"ok\"\n\t| \"limited\"\n\t| \"wrong\"\n\t| \"expired\"\n\t| \"locked\"\n\t| \"inactive\"\n\t| \"malformed\";\n\n/** Six uniformly distributed digits. */\nexport function newPairingCode(): string {\n\t// 4 294 000 000 is the largest multiple of 10^6 below 2^32: rejecting the\n\t// values above it keeps every code equally likely.\n\tconst buffer = new Uint32Array(1);\n\tfor (;;) {\n\t\tcrypto.getRandomValues(buffer);\n\t\tconst n = buffer[0] ?? 0;\n\t\tif (n < 4_294_000_000) return String(n % 1_000_000).padStart(6, \"0\");\n\t}\n}\n\nfunction sameCode(a: string, b: string): boolean {\n\tconst x = Buffer.from(a);\n\tconst y = Buffer.from(b);\n\treturn x.length === y.length && timingSafeEqual(x, y);\n}\n\n/**\n * The pairing codes of one tab session: on while the tab's dialog is open\n * (`pairing.start` … `pairing.stop`); a fresh code after expiry, after use and\n * after too many wrong attempts. Codes are never logged.\n */\nexport class PairingCodes {\n\treadonly #send: (code: string, expiresAt: number) => void;\n\treadonly #ttlMs: number;\n\treadonly #maxAttempts: number;\n\t#current: { code: string; expiresAt: number; attempts: number } | undefined;\n\t#previous: string | undefined;\n\t#timer: Timer | undefined;\n\n\tconstructor(\n\t\tsend: (code: string, expiresAt: number) => void,\n\t\toptions: { ttlMs?: number; maxAttempts?: number } = {},\n\t) {\n\t\tthis.#send = send;\n\t\tthis.#ttlMs = options.ttlMs ?? PAIRING_CODE_TTL_MS;\n\t\tthis.#maxAttempts = options.maxAttempts ?? PAIRING_MAX_ATTEMPTS;\n\t}\n\n\t/** Whether the tab is showing codes. */\n\tget active(): boolean {\n\t\treturn this.#current !== undefined;\n\t}\n\n\t/** Attempts left for the current code. */\n\tget attemptsLeft(): number {\n\t\treturn this.#current === undefined\n\t\t\t? 0\n\t\t\t: this.#maxAttempts - this.#current.attempts;\n\t}\n\n\tstart(): void {\n\t\tif (this.#current !== undefined) {\n\t\t\t// Already on (e.g. a second dialog): show the same code again.\n\t\t\tthis.#send(this.#current.code, this.#current.expiresAt);\n\t\t\treturn;\n\t\t}\n\t\tthis.#issue();\n\t}\n\n\tstop(): void {\n\t\tclearTimeout(this.#timer);\n\t\tthis.#timer = undefined;\n\t\tthis.#current = undefined;\n\t\tthis.#previous = undefined;\n\t}\n\n\t/**\n\t * Check a typed code; a correct one is used up and replaced. `admit` is\n\t * asked only for a well-formed code while a code is active.\n\t */\n\tcheck(\n\t\tinput: string,\n\t\tnow: number = Date.now(),\n\t\tadmit: () => boolean = () => true,\n\t): CodeCheck {\n\t\tconst current = this.#current;\n\t\tif (current === undefined) return \"inactive\";\n\t\tconst typed = input.replace(/[\\s-]/g, \"\");\n\t\tif (!/^\\d{6}$/.test(typed)) return \"malformed\";\n\t\tif (!admit()) return \"limited\";\n\t\tif (now >= current.expiresAt) {\n\t\t\tthis.#previous = current.code;\n\t\t\tthis.#issue();\n\t\t\treturn \"expired\";\n\t\t}\n\t\tif (sameCode(typed, current.code)) {\n\t\t\tthis.#previous = undefined;\n\t\t\tthis.#issue();\n\t\t\treturn \"ok\";\n\t\t}\n\t\tcurrent.attempts++;\n\t\tconst expired =\n\t\t\tthis.#previous !== undefined && sameCode(typed, this.#previous);\n\t\tif (current.attempts >= this.#maxAttempts) {\n\t\t\tthis.#previous = undefined;\n\t\t\tthis.#issue();\n\t\t\treturn \"locked\";\n\t\t}\n\t\treturn expired ? \"expired\" : \"wrong\";\n\t}\n\n\t#issue(): void {\n\t\tclearTimeout(this.#timer);\n\t\tconst expiresAt = Date.now() + this.#ttlMs;\n\t\tthis.#current = { code: newPairingCode(), expiresAt, attempts: 0 };\n\t\tthis.#timer = setTimeout(() => {\n\t\t\tif (this.#current === undefined) return;\n\t\t\tthis.#previous = this.#current.code;\n\t\t\tthis.#issue();\n\t\t}, this.#ttlMs);\n\t\tthis.#send(this.#current.code, expiresAt);\n\t}\n}\n\nconst MESSAGES: Record<Exclude<CodeCheck, \"ok\">, string> = {\n\twrong:\n\t\t\"That code is not right. Check the code shown in the page and try again.\",\n\texpired:\n\t\t\"That code has expired. The page now shows a new code: enter that one.\",\n\tlocked:\n\t\t\"Too many wrong codes. The page now shows a new code: enter that one.\",\n\tinactive:\n\t\t\"The page is not showing a code right now. In the page, open “Connect your AI app” to see one, then enter it here.\",\n\tmalformed: \"Enter the 6 digits shown in the page.\",\n\tlimited:\n\t\t\"Too many attempts for this page. Wait a few minutes and try again. If it keeps happening, someone else may be guessing: use “New address” in the page.\",\n};\n\n/** The 6-digit code typed at `/authorize` (DEC-028). */\nexport const codePairing: PairingMethod = {\n\tkind: \"code\",\n\trender(): string {\n\t\treturn `<p><label for=\"code\">Code shown in the page</label>\n<input id=\"code\" name=\"code\" type=\"text\" inputmode=\"numeric\" autocomplete=\"one-time-code\" pattern=\"[0-9 ]{6,7}\" maxlength=\"7\" required autofocus aria-describedby=\"code-help\"></p>\n<p id=\"code-help\" class=\"help\">In the page, “Connect your AI app” shows a 6-digit code. It changes every 2 minutes.</p>`;\n\t},\n\tcheck(target, form, admit): PairingResult {\n\t\tconst result = target.codes.check(\n\t\t\tform.get(\"code\") ?? \"\",\n\t\t\tDate.now(),\n\t\t\tadmit,\n\t\t);\n\t\tif (result === \"ok\") return { ok: true };\n\t\tlet message = MESSAGES[result];\n\t\tif (result === \"wrong\") {\n\t\t\tconst left = target.codes.attemptsLeft;\n\t\t\tmessage += ` ${left === 1 ? \"1 try is\" : `${left} tries are`} left for this code.`;\n\t\t}\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage,\n\t\t\treason: result === \"limited\" ? \"rate_limited\" : result,\n\t\t};\n\t},\n};\n\n/** The methods by kind. `oidc` joins with identity binding (DEC-042). */\nexport const PAIRING_METHODS: Partial<Record<PairingKind, PairingMethod>> = {\n\tcode: codePairing,\n};\n",
|
|
17
17
|
"import {\n\taddressIdFromSecret,\n\tisWellFormedSecret,\n\tshortAddress,\n} from \"./address.ts\";\nimport type { RelayConfig, Site, SiteLimits } from \"./config.ts\";\nimport { Exchange, RelayErrorCode, type RpcId } from \"./exchange.ts\";\nimport type { Logger } from \"./log.ts\";\nimport { PairingCodes } from \"./oauth/pairing.ts\";\nimport {\n\ttype ByeReason,\n\tCloseCode,\n\ttype ErrorCode,\n\ttype GrantInfo,\n\ttype GrantRef,\n\ttype Limits,\n\ttype ParseResult,\n\tparseTabMessage,\n\ttype RelayMessage,\n\ttype TabMessage,\n} from \"./protocol.ts\";\nimport type { TokenStore } from \"./store/types.ts\";\nimport { newId } from \"./tokens.ts\";\n\n/** The part of Bun's `ServerWebSocket` a session uses (a fake in unit tests). */\nexport interface SocketLike {\n\t/** Bytes sent, -1 when queued under backpressure, 0 when dropped. */\n\tsend(data: string): number;\n\tclose(code?: number, reason?: string): void;\n}\n\n/** What a session needs from its relay. */\nexport interface SessionHost {\n\treadonly config: RelayConfig;\n\treadonly logger: Logger;\n\treadonly store: TokenStore;\n\t/** The external origin, e.g. `https://relay.ractive.ch`. */\n\tpublicUrl(): string;\n\t/** Register a session for its address; returns the session it replaced. */\n\tclaimAddress(session: TabSession): TabSession | undefined;\n\t/** Called once when a session is over. */\n\treleased(session: TabSession): void;\n\t/** The tab pressed Disconnect for one app; false if the grant is not this address's. */\n\trevokeGrant(session: TabSession, grantId: string): Promise<boolean>;\n\t/** The tab revokes every grant of its address (\"New address\"). */\n\trevokeAll(session: TabSession): Promise<void>;\n\t/** Pairing code lifetime (tests shorten it). */\n\treadonly pairingCodeTtlMs?: number;\n}\n\nexport interface ForwardInput {\n\tmethod: string;\n\theaders: Record<string, string>;\n\tbody: string;\n\trpcId: RpcId | undefined;\n\tisListen: boolean;\n\tgrant: GrantRef;\n\textraHeaders: Record<string, string>;\n\t/** Called once with the finished exchange (for the request log line). */\n\tonDone: (exchange: Exchange) => void;\n}\n\n/** The limits announced to the tab (protocol: `session.limits`). */\nexport function limitsOf(limits: SiteLimits | RelayConfig): Limits {\n\treturn {\n\t\tmaxMessageBytes: limits.maxMessageBytes,\n\t\tmaxBodyBytes: limits.maxMessageBytes,\n\t\trequestTimeoutMs: limits.requestTimeoutMs,\n\t\tidleTimeoutMs: limits.idleTimeoutMs,\n\t\theartbeatMs: limits.heartbeatMs,\n\t\tkeepAliveMs: limits.keepAliveMs,\n\t\tmaxConcurrentRequests: limits.maxConcurrentRequests,\n\t};\n}\n\nfunction clientHost(clientId: string): string {\n\ttry {\n\t\treturn new URL(clientId).host;\n\t} catch {\n\t\treturn \"\";\n\t}\n}\n\n/** The request id a parsed frame refers to, if any. */\nfunction messageId(parsed: ParseResult): string | undefined {\n\tif (\"message\" in parsed) {\n\t\treturn \"id\" in parsed.message ? parsed.message.id : undefined;\n\t}\n\treturn parsed.id;\n}\n\n/** One tab's WebSocket session, from open to close. */\nexport class TabSession {\n\treadonly sessionId: string = newId(\"s\");\n\treadonly ip: string;\n\treadonly origin: string;\n\t/** The site this session's origin belongs to (DEC-045). */\n\treadonly site: Site;\n\treadonly openedAt: number = Date.now();\n\t/** Set once `hello` was accepted. */\n\taddressId: string | undefined;\n\t/** The app name `/authorize` shows: the site's name, else the page's claim. */\n\tappName: string | undefined;\n\t/** Pairing codes while the tab's dialog is open (DEC-028). */\n\treadonly codes: PairingCodes;\n\treadonly pending: Map<string, Exchange> = new Map();\n\n\treadonly #ws: SocketLike;\n\treadonly #host: SessionHost;\n\t#state: \"new\" | \"hello\" | \"ready\" | \"ended\" = \"new\";\n\t#lastRequestAt = Date.now();\n\t#missedPongs = 0;\n\t#nextRequest = 0;\n\t#helloTimer: Timer | undefined;\n\t#heartbeatTimer: Timer | undefined;\n\t#lifetimeTimer: Timer | undefined;\n\n\tconstructor(\n\t\tws: SocketLike,\n\t\tip: string,\n\t\torigin: string,\n\t\tsite: Site,\n\t\thost: SessionHost,\n\t) {\n\t\tthis.#ws = ws;\n\t\tthis.ip = ip;\n\t\tthis.origin = origin;\n\t\tthis.site = site;\n\t\tthis.#host = host;\n\t\tthis.codes = new PairingCodes(\n\t\t\t(code, expiresAt) => {\n\t\t\t\tthis.send({\n\t\t\t\t\ttype: \"pairing.code\",\n\t\t\t\t\tcode,\n\t\t\t\t\texpiresAt: new Date(expiresAt).toISOString(),\n\t\t\t\t});\n\t\t\t},\n\t\t\thost.pairingCodeTtlMs === undefined\n\t\t\t\t? {}\n\t\t\t\t: { ttlMs: host.pairingCodeTtlMs },\n\t\t);\n\t\tthis.#helloTimer = setTimeout(() => {\n\t\t\tif (this.#state === \"new\") {\n\t\t\t\tthis.#protocolError(\"bad_message\", \"no hello in time\");\n\t\t\t}\n\t\t}, host.config.helloTimeoutMs);\n\t}\n\n\tget ready(): boolean {\n\t\treturn this.#state === \"ready\";\n\t}\n\n\t/** The limits of this session (its site's). */\n\tget limits(): SiteLimits {\n\t\treturn this.site.limits;\n\t}\n\n\t/** Send one message; false if Bun dropped it under backpressure (DEC-021). */\n\tsend(message: RelayMessage): boolean {\n\t\tif (this.#state === \"ended\") return false;\n\t\tlet sent: number;\n\t\ttry {\n\t\t\tsent = this.#ws.send(JSON.stringify(message));\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t\tif (sent === 0) {\n\t\t\tthis.#host.logger.warn(\"tab.send_dropped\", {\n\t\t\t\tsession: this.sessionId,\n\t\t\t\ttype: message.type,\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/** A frame arrived from the tab. */\n\thandleFrame(data: string | Uint8Array): void {\n\t\tif (this.#state === \"ended\") return;\n\t\tif (typeof data !== \"string\") {\n\t\t\tthis.#protocolError(\"bad_message\", \"binary frames are not allowed\");\n\t\t\treturn;\n\t\t}\n\t\tconst tooLarge = Buffer.byteLength(data) > this.limits.maxMessageBytes;\n\t\tconst parsed = parseTabMessage(data);\n\t\tif (tooLarge) {\n\t\t\tconst id = messageId(parsed);\n\t\t\tthis.#sendError(\"too_large\", \"message exceeds maxMessageBytes\", id);\n\t\t\tconst exchange = id === undefined ? undefined : this.pending.get(id);\n\t\t\texchange?.fail(\n\t\t\t\t502,\n\t\t\t\tRelayErrorCode.tooLarge,\n\t\t\t\t\"The page sent a response that is too large.\",\n\t\t\t\ttrue,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (!parsed.ok) {\n\t\t\tif (this.#state === \"new\") {\n\t\t\t\tthis.#protocolError(\"bad_message\", parsed.error);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.#sendError(\"bad_message\", parsed.error, parsed.id);\n\t\t\t// A malformed response must not leave its request hanging.\n\t\t\tconst exchange =\n\t\t\t\tparsed.id === undefined ? undefined : this.pending.get(parsed.id);\n\t\t\texchange?.fail(\n\t\t\t\t502,\n\t\t\t\tRelayErrorCode.badResponse,\n\t\t\t\t\"The page sent an invalid response.\",\n\t\t\t\ttrue,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (\"unknown\" in parsed) {\n\t\t\tif (this.#state === \"new\") {\n\t\t\t\tthis.#protocolError(\"bad_message\", \"hello expected\");\n\t\t\t} else if (parsed.id !== undefined) {\n\t\t\t\tthis.#sendError(\n\t\t\t\t\t\"unknown_type\",\n\t\t\t\t\t`unknown type ${parsed.type}`,\n\t\t\t\t\tparsed.id,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t// One bad frame must never become an unhandled rejection (it would end\n\t\t// the process): log it, tell the tab, keep the session.\n\t\tthis.#handle(parsed.message).catch((error: unknown) => {\n\t\t\tthis.#host.logger.error(\"tab.handler_error\", {\n\t\t\t\tsession: this.sessionId,\n\t\t\t\ttype: parsed.message.type,\n\t\t\t\tmessage: error instanceof Error ? error.name : \"unknown\",\n\t\t\t});\n\t\t\tthis.#sendError(\"bad_message\", \"the relay could not handle this message\");\n\t\t});\n\t}\n\n\tasync #handle(msg: TabMessage): Promise<void> {\n\t\tif (this.#state === \"new\") {\n\t\t\tif (msg.type !== \"hello\") {\n\t\t\t\tthis.#protocolError(\"bad_message\", \"hello expected\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait this.#hello(msg.secret, msg.library, msg.app?.name);\n\t\t\treturn;\n\t\t}\n\t\tif (this.#state === \"hello\") return; // still answering hello\n\t\tswitch (msg.type) {\n\t\t\tcase \"hello\":\n\t\t\t\tthis.#sendError(\"bad_message\", \"hello was already sent\");\n\t\t\t\treturn;\n\t\t\tcase \"pong\":\n\t\t\t\tthis.#missedPongs = 0;\n\t\t\t\treturn;\n\t\t\tcase \"bye\":\n\t\t\t\tthis.end(CloseCode.normal, \"bye\");\n\t\t\t\treturn;\n\t\t\tcase \"pairing.start\":\n\t\t\t\tif (this.site.pairing === \"code\") this.codes.start();\n\t\t\t\treturn;\n\t\t\tcase \"pairing.stop\":\n\t\t\t\tthis.codes.stop();\n\t\t\t\treturn;\n\t\t\tcase \"grant.revoke\":\n\t\t\t\tif (!(await this.#host.revokeGrant(this, msg.grantId))) {\n\t\t\t\t\tthis.#sendError(\"unknown_id\", \"unknown grant\");\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase \"grants.revokeAll\":\n\t\t\t\tawait this.#host.revokeAll(this);\n\t\t\t\treturn;\n\t\t\tcase \"error\":\n\t\t\t\tthis.#host.logger.debug(\"tab.error\", {\n\t\t\t\t\tsession: this.sessionId,\n\t\t\t\t\tcode: msg.code,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\tcase \"http.response\":\n\t\t\tcase \"http.response.start\":\n\t\t\tcase \"http.response.chunk\":\n\t\t\tcase \"http.response.end\": {\n\t\t\t\tconst exchange = this.pending.get(msg.id);\n\t\t\t\tif (exchange === undefined) return; // finished or cancelled: drop\n\t\t\t\tif (msg.type === \"http.response\") exchange.onResponse(msg);\n\t\t\t\telse if (msg.type === \"http.response.start\") exchange.onStart(msg);\n\t\t\t\telse if (msg.type === \"http.response.chunk\") exchange.onChunk(msg.data);\n\t\t\t\telse exchange.onEnd();\n\t\t\t\tif (exchange.badResponseReason !== undefined) {\n\t\t\t\t\tthis.#sendError(\"bad_message\", exchange.badResponseReason, msg.id);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #hello(\n\t\tsecret: string,\n\t\tlibrary: { name: string; version: string },\n\t\tappName: string | undefined,\n\t): Promise<void> {\n\t\tif (!isWellFormedSecret(secret)) {\n\t\t\tthis.#protocolError(\n\t\t\t\t\"bad_message\",\n\t\t\t\t\"secret must be 43 base64url characters\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tclearTimeout(this.#helloTimer);\n\t\tthis.#state = \"hello\";\n\t\tthis.addressId = addressIdFromSecret(secret);\n\t\tthis.appName = this.site.name ?? appName;\n\t\tconst replaced = this.#host.claimAddress(this);\n\t\tif (replaced !== undefined) {\n\t\t\treplaced.end(\n\t\t\t\tCloseCode.replaced,\n\t\t\t\t\"replaced by a newer session\",\n\t\t\t\t\"replaced\",\n\t\t\t);\n\t\t}\n\n\t\tlet grants: GrantInfo[] = [];\n\t\ttry {\n\t\t\tconst list = await this.#host.store.listGrants(\n\t\t\t\tthis.addressId,\n\t\t\t\tDate.now(),\n\t\t\t);\n\t\t\tgrants = list.map((g) => ({\n\t\t\t\tgrantId: g.grantId,\n\t\t\t\tclient: {\n\t\t\t\t\tid: g.clientId,\n\t\t\t\t\tname: g.clientName,\n\t\t\t\t\thost: clientHost(g.clientId),\n\t\t\t\t},\n\t\t\t\tcreatedAt: new Date(g.createdAt).toISOString(),\n\t\t\t}));\n\t\t} catch (error) {\n\t\t\tthis.#host.logger.error(\"store.error\", {\n\t\t\t\top: \"listGrants\",\n\t\t\t\tmessage: error instanceof Error ? error.message : \"unknown\",\n\t\t\t});\n\t\t}\n\t\tif (this.#state !== \"hello\") return; // closed meanwhile\n\n\t\tconst limits = this.limits;\n\t\tconst expiresAt = this.openedAt + limits.sessionLifetimeMs;\n\t\tthis.#state = \"ready\";\n\t\tconst sent = this.send({\n\t\t\ttype: \"session\",\n\t\t\tsessionId: this.sessionId,\n\t\t\taddress: `${this.#host.publicUrl()}/a/${this.addressId}/mcp`,\n\t\t\torigin: this.origin,\n\t\t\t...(this.appName === undefined ? {} : { appName: this.appName }),\n\t\t\texpiresAt: new Date(expiresAt).toISOString(),\n\t\t\tlimits: limitsOf(limits),\n\t\t\tgrants,\n\t\t});\n\t\tif (!sent) {\n\t\t\tthis.end(CloseCode.policyViolation, \"send failed\");\n\t\t\treturn;\n\t\t}\n\t\tthis.#heartbeatTimer = setInterval(() => this.#tick(), limits.heartbeatMs);\n\t\tthis.#lifetimeTimer = setTimeout(\n\t\t\t() =>\n\t\t\t\tthis.end(\n\t\t\t\t\tCloseCode.sessionExpired,\n\t\t\t\t\t\"session lifetime reached\",\n\t\t\t\t\t\"expired\",\n\t\t\t\t),\n\t\t\tMath.max(0, expiresAt - Date.now()),\n\t\t);\n\t\tthis.#host.logger.info(\"tab.session\", {\n\t\t\tsession: this.sessionId,\n\t\t\taddress: shortAddress(this.addressId),\n\t\t\torigin: this.origin,\n\t\t\tlibrary: `${library.name}@${library.version}`,\n\t\t\treplaced: replaced !== undefined,\n\t\t});\n\t}\n\n\t#tick(): void {\n\t\tif (this.#state !== \"ready\") return;\n\t\tif (this.#missedPongs >= 2) {\n\t\t\tthis.end(CloseCode.heartbeatLost, \"heartbeat lost\");\n\t\t\treturn;\n\t\t}\n\t\t// Idle = no MCP request and nothing in flight, listen streams included:\n\t\t// a listen stream may stay open for the session's lifetime (protocol.md),\n\t\t// which still caps it.\n\t\tif (\n\t\t\tthis.pending.size === 0 &&\n\t\t\tDate.now() - this.#lastRequestAt >= this.limits.idleTimeoutMs\n\t\t) {\n\t\t\tthis.end(CloseCode.idleTimeout, \"idle\", \"idle\");\n\t\t\treturn;\n\t\t}\n\t\tthis.#missedPongs++;\n\t\tthis.send({ type: \"ping\", t: Date.now() });\n\t}\n\n\t/** Tunnel one MCP request to the tab. Resolves with the AI app's response. */\n\tforward(input: ForwardInput): Exchange {\n\t\tthis.#lastRequestAt = Date.now();\n\t\tconst id = `r${++this.#nextRequest}`;\n\t\tconst limits = this.limits;\n\t\tconst exchange = new Exchange({\n\t\t\tid,\n\t\t\trpcId: input.rpcId,\n\t\t\tisListen: input.isListen,\n\t\t\trequestTimeoutMs: limits.requestTimeoutMs,\n\t\t\tkeepAliveMs: limits.keepAliveMs,\n\t\t\tmaxBodyBytes: limitsOf(limits).maxBodyBytes,\n\t\t\textraHeaders: input.extraHeaders,\n\t\t\tcancel: (reason) => {\n\t\t\t\tif (!this.send({ type: \"http.cancel\", id, reason })) {\n\t\t\t\t\tthis.#host.logger.debug(\"tab.cancel_not_sent\", {\n\t\t\t\t\t\tsession: this.sessionId,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tonDone: (e) => {\n\t\t\t\tthis.pending.delete(id);\n\t\t\t\tthis.#lastRequestAt = Date.now();\n\t\t\t\tinput.onDone(e);\n\t\t\t},\n\t\t});\n\t\tthis.pending.set(id, exchange);\n\t\tconst sent = this.send({\n\t\t\ttype: \"http.request\",\n\t\t\tid,\n\t\t\tmethod: input.method,\n\t\t\tpath: \"/mcp\",\n\t\t\theaders: input.headers,\n\t\t\tbody: input.body,\n\t\t\tgrant: input.grant,\n\t\t});\n\t\tif (!sent) {\n\t\t\texchange.fail(\n\t\t\t\t503,\n\t\t\t\tRelayErrorCode.sendFailed,\n\t\t\t\t\"The connection to the page is overloaded. Try again.\",\n\t\t\t\tfalse,\n\t\t\t);\n\t\t}\n\t\treturn exchange;\n\t}\n\n\t/** End the session: optional `bye`, then close the socket. Idempotent. */\n\tend(code: number, reason: string, bye?: ByeReason): void {\n\t\tif (this.#state === \"ended\") return;\n\t\tif (bye !== undefined) this.send({ type: \"bye\", reason: bye });\n\t\tthis.#cleanup(code, reason);\n\t\ttry {\n\t\t\tthis.#ws.close(code, reason);\n\t\t} catch {\n\t\t\t// already closed\n\t\t}\n\t}\n\n\t/** The socket closed (from Bun's `close` handler). */\n\tclosed(code: number): void {\n\t\tthis.#cleanup(code, \"closed\");\n\t}\n\n\t#cleanup(code: number, reason: string): void {\n\t\tif (this.#state === \"ended\") return;\n\t\tconst wasReady = this.#state === \"ready\" || this.#state === \"hello\";\n\t\tthis.#state = \"ended\";\n\t\tthis.codes.stop();\n\t\tclearTimeout(this.#helloTimer);\n\t\tclearInterval(this.#heartbeatTimer);\n\t\tclearTimeout(this.#lifetimeTimer);\n\t\tfor (const exchange of [...this.pending.values()]) {\n\t\t\texchange.fail(\n\t\t\t\t503,\n\t\t\t\tRelayErrorCode.tabGone,\n\t\t\t\t\"The page closed its connection to the relay.\",\n\t\t\t\tfalse,\n\t\t\t);\n\t\t}\n\t\tthis.#host.released(this);\n\t\tif (wasReady) {\n\t\t\tthis.#host.logger.info(\"tab.closed\", {\n\t\t\t\tsession: this.sessionId,\n\t\t\t\tcode,\n\t\t\t\treason,\n\t\t\t\tdurationMs: Date.now() - this.openedAt,\n\t\t\t});\n\t\t}\n\t}\n\n\t#sendError(code: ErrorCode, message: string, id?: string): void {\n\t\tthis.send(\n\t\t\tid === undefined\n\t\t\t\t? { type: \"error\", code, message }\n\t\t\t\t: { type: \"error\", code, message, id },\n\t\t);\n\t}\n\n\t#protocolError(code: ErrorCode, message: string): void {\n\t\tthis.#sendError(code, message);\n\t\tthis.end(CloseCode.policyViolation, message);\n\t}\n}\n",
|
|
18
18
|
"import type {\n\tGrantSummary,\n\tRevokeOptions,\n\tRevokeSelector,\n\tTokenRecord,\n\tTokenStore,\n} from \"./types.ts\";\n\nfunction copy(record: TokenRecord): TokenRecord {\n\treturn { ...record, scopes: [...record.scopes] };\n}\n\nfunction matches(record: TokenRecord, selector: RevokeSelector): boolean {\n\treturn \"grantId\" in selector\n\t\t? record.grantId === selector.grantId\n\t\t: record.addressId === selector.addressId;\n}\n\n/** Usable at `now`: unexpired, and for refresh tokens not yet used. */\nexport function isLive(record: TokenRecord, now: number): boolean {\n\treturn (\n\t\trecord.expiresAt > now &&\n\t\t(record.kind === \"access\" || record.usedAt === undefined)\n\t);\n}\n\n/** Group live records into grant summaries, oldest grant first. */\nexport function summarizeGrants(\n\trecords: Iterable<TokenRecord>,\n\tnow: number,\n): GrantSummary[] {\n\tconst grants = new Map<string, GrantSummary>();\n\tfor (const r of records) {\n\t\tif (!isLive(r, now) || grants.has(r.grantId)) continue;\n\t\tgrants.set(r.grantId, {\n\t\t\tgrantId: r.grantId,\n\t\t\tclientId: r.clientId,\n\t\t\tclientName: r.clientName,\n\t\t\tscopes: [...r.scopes],\n\t\t\tcreatedAt: r.grantCreatedAt,\n\t\t});\n\t}\n\treturn [...grants.values()].sort(\n\t\t(a, b) => a.createdAt - b.createdAt || a.grantId.localeCompare(b.grantId),\n\t);\n}\n\n/** Tokens in process memory; everything is lost on restart. */\nexport class MemoryTokenStore implements TokenStore {\n\treadonly #records = new Map<string, TokenRecord>();\n\t/** Revoked grants: grant id → keep until. */\n\treadonly #revokedGrants = new Map<string, number>();\n\t/** Revoked addresses: address id → { at, keep until }. */\n\treadonly #revokedAddresses = new Map<string, { at: number; until: number }>();\n\n\tasync put(record: TokenRecord): Promise<boolean> {\n\t\tif (this.#revokedGrants.has(record.grantId)) return false;\n\t\tconst address = this.#revokedAddresses.get(record.addressId);\n\t\tif (address !== undefined && record.grantCreatedAt <= address.at) {\n\t\t\treturn false;\n\t\t}\n\t\tthis.#records.set(record.hash, copy(record));\n\t\treturn true;\n\t}\n\n\tasync get(hash: string): Promise<TokenRecord | undefined> {\n\t\tconst r = this.#records.get(hash);\n\t\treturn r === undefined ? undefined : copy(r);\n\t}\n\n\tasync markUsed(hash: string, now: number): Promise<boolean> {\n\t\tconst r = this.#records.get(hash);\n\t\tif (r === undefined || r.usedAt !== undefined) return false;\n\t\tr.usedAt = now;\n\t\treturn true;\n\t}\n\n\tasync revoke(\n\t\tselector: RevokeSelector,\n\t\toptions: RevokeOptions,\n\t): Promise<number> {\n\t\tif (\"grantId\" in selector) {\n\t\t\tthis.#revokedGrants.set(selector.grantId, options.keepUntil);\n\t\t} else {\n\t\t\tconst old = this.#revokedAddresses.get(selector.addressId);\n\t\t\tthis.#revokedAddresses.set(selector.addressId, {\n\t\t\t\tat: Math.max(old?.at ?? 0, options.now),\n\t\t\t\tuntil: Math.max(old?.until ?? 0, options.keepUntil),\n\t\t\t});\n\t\t}\n\t\tlet n = 0;\n\t\tfor (const [hash, r] of this.#records) {\n\t\t\tif (matches(r, selector)) {\n\t\t\t\tthis.#records.delete(hash);\n\t\t\t\tn++;\n\t\t\t}\n\t\t}\n\t\treturn n;\n\t}\n\n\tasync listGrants(addressId: string, now: number): Promise<GrantSummary[]> {\n\t\tconst own = [...this.#records.values()].filter(\n\t\t\t(r) => r.addressId === addressId,\n\t\t);\n\t\treturn summarizeGrants(own, now);\n\t}\n\n\tasync deleteExpired(now: number): Promise<number> {\n\t\tfor (const [id, until] of this.#revokedGrants) {\n\t\t\tif (until <= now) this.#revokedGrants.delete(id);\n\t\t}\n\t\tfor (const [id, t] of this.#revokedAddresses) {\n\t\t\tif (t.until <= now) this.#revokedAddresses.delete(id);\n\t\t}\n\t\tlet n = 0;\n\t\tfor (const [hash, r] of this.#records) {\n\t\t\tif (r.expiresAt <= now) {\n\t\t\t\tthis.#records.delete(hash);\n\t\t\t\tn++;\n\t\t\t}\n\t\t}\n\t\treturn n;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.#records.clear();\n\t\tthis.#revokedGrants.clear();\n\t\tthis.#revokedAddresses.clear();\n\t}\n}\n",
|
|
19
19
|
"import { Database } from \"bun:sqlite\";\nimport { summarizeGrants } from \"./memory.ts\";\nimport type {\n\tGrantSummary,\n\tRevokeOptions,\n\tRevokeSelector,\n\tTokenKind,\n\tTokenRecord,\n\tTokenStore,\n} from \"./types.ts\";\n\nconst SCHEMA_VERSION = 2;\n\ninterface Row {\n\thash: string;\n\tkind: string;\n\tgrant_id: string;\n\taddress_id: string;\n\tclient_id: string;\n\tclient_name: string;\n\tscopes: string;\n\tgrant_created_at: number;\n\tissued_at: number;\n\texpires_at: number;\n\tused_at: number | null;\n}\n\nfunction toRecord(row: Row): TokenRecord {\n\tconst record: TokenRecord = {\n\t\thash: row.hash,\n\t\tkind: row.kind as TokenKind,\n\t\tgrantId: row.grant_id,\n\t\taddressId: row.address_id,\n\t\tclientId: row.client_id,\n\t\tclientName: row.client_name,\n\t\tscopes: JSON.parse(row.scopes) as string[],\n\t\tgrantCreatedAt: row.grant_created_at,\n\t\tissuedAt: row.issued_at,\n\t\texpiresAt: row.expires_at,\n\t};\n\tif (row.used_at !== null) record.usedAt = row.used_at;\n\treturn record;\n}\n\n/**\n * Tokens in a SQLite file via `bun:sqlite` (the default store, DEC-030). Uses\n * WAL mode so another process (or a test) can read and write the same file.\n */\nexport class SqliteTokenStore implements TokenStore {\n\treadonly #db: Database;\n\n\t/** `path` is a file path, or `:memory:`. */\n\tconstructor(path: string) {\n\t\tthis.#db = new Database(path, { create: true, strict: true });\n\t\tthis.#db.run(\"PRAGMA busy_timeout = 5000\");\n\t\tif (path !== \":memory:\") this.#db.run(\"PRAGMA journal_mode = WAL\");\n\t\tthis.#migrate();\n\t}\n\n\t#migrate(): void {\n\t\tconst row = this.#db.query(\"PRAGMA user_version\").get() as {\n\t\t\tuser_version: number;\n\t\t};\n\t\tif (row.user_version >= SCHEMA_VERSION) return;\n\t\tthis.#db.transaction(() => {\n\t\t\t// Version 2: tombstones of revoked grants and addresses.\n\t\t\tthis.#db.run(`CREATE TABLE IF NOT EXISTS revocations (\n\t\t\t\tkind TEXT NOT NULL CHECK (kind IN ('grant', 'address')),\n\t\t\t\tid TEXT NOT NULL,\n\t\t\t\tat INTEGER NOT NULL,\n\t\t\t\tkeep_until INTEGER NOT NULL,\n\t\t\t\tPRIMARY KEY (kind, id)\n\t\t\t) STRICT`);\n\t\t\tthis.#db.run(`CREATE TABLE IF NOT EXISTS tokens (\n\t\t\t\thash TEXT PRIMARY KEY,\n\t\t\t\tkind TEXT NOT NULL CHECK (kind IN ('access', 'refresh')),\n\t\t\t\tgrant_id TEXT NOT NULL,\n\t\t\t\taddress_id TEXT NOT NULL,\n\t\t\t\tclient_id TEXT NOT NULL,\n\t\t\t\tclient_name TEXT NOT NULL,\n\t\t\t\tscopes TEXT NOT NULL,\n\t\t\t\tgrant_created_at INTEGER NOT NULL,\n\t\t\t\tissued_at INTEGER NOT NULL,\n\t\t\t\texpires_at INTEGER NOT NULL,\n\t\t\t\tused_at INTEGER\n\t\t\t) STRICT`);\n\t\t\tthis.#db.run(\n\t\t\t\t\"CREATE INDEX IF NOT EXISTS tokens_grant ON tokens (grant_id)\",\n\t\t\t);\n\t\t\tthis.#db.run(\n\t\t\t\t\"CREATE INDEX IF NOT EXISTS tokens_address ON tokens (address_id)\",\n\t\t\t);\n\t\t\tthis.#db.run(\n\t\t\t\t\"CREATE INDEX IF NOT EXISTS tokens_expires ON tokens (expires_at)\",\n\t\t\t);\n\t\t\tthis.#db.run(`PRAGMA user_version = ${SCHEMA_VERSION}`);\n\t\t})();\n\t}\n\n\tasync put(r: TokenRecord): Promise<boolean> {\n\t\treturn this.#db.transaction(() => {\n\t\t\tconst revoked = this.#db\n\t\t\t\t.query(\n\t\t\t\t\t`SELECT 1 FROM revocations WHERE (kind = 'grant' AND id = $grant_id)\n\t\t\t\t\tOR (kind = 'address' AND id = $address_id AND at >= $created)`,\n\t\t\t\t)\n\t\t\t\t.get({\n\t\t\t\t\tgrant_id: r.grantId,\n\t\t\t\t\taddress_id: r.addressId,\n\t\t\t\t\tcreated: r.grantCreatedAt,\n\t\t\t\t});\n\t\t\tif (revoked !== null) return false;\n\t\t\tthis.#insert(r);\n\t\t\treturn true;\n\t\t})();\n\t}\n\n\t#insert(r: TokenRecord): void {\n\t\tthis.#db\n\t\t\t.query(\n\t\t\t\t`INSERT OR REPLACE INTO tokens (hash, kind, grant_id, address_id, client_id,\n\t\t\t\tclient_name, scopes, grant_created_at, issued_at, expires_at, used_at)\n\t\t\t\tVALUES ($hash, $kind, $grant_id, $address_id, $client_id, $client_name,\n\t\t\t\t$scopes, $grant_created_at, $issued_at, $expires_at, $used_at)`,\n\t\t\t)\n\t\t\t.run({\n\t\t\t\thash: r.hash,\n\t\t\t\tkind: r.kind,\n\t\t\t\tgrant_id: r.grantId,\n\t\t\t\taddress_id: r.addressId,\n\t\t\t\tclient_id: r.clientId,\n\t\t\t\tclient_name: r.clientName,\n\t\t\t\tscopes: JSON.stringify(r.scopes),\n\t\t\t\tgrant_created_at: r.grantCreatedAt,\n\t\t\t\tissued_at: r.issuedAt,\n\t\t\t\texpires_at: r.expiresAt,\n\t\t\t\tused_at: r.usedAt ?? null,\n\t\t\t});\n\t}\n\n\tasync get(hash: string): Promise<TokenRecord | undefined> {\n\t\tconst row = this.#db\n\t\t\t.query(\"SELECT * FROM tokens WHERE hash = $hash\")\n\t\t\t.get({ hash }) as Row | null;\n\t\treturn row === null ? undefined : toRecord(row);\n\t}\n\n\tasync markUsed(hash: string, now: number): Promise<boolean> {\n\t\tconst result = this.#db\n\t\t\t.query(\n\t\t\t\t\"UPDATE tokens SET used_at = $now WHERE hash = $hash AND used_at IS NULL\",\n\t\t\t)\n\t\t\t.run({ hash, now });\n\t\treturn result.changes === 1;\n\t}\n\n\tasync revoke(\n\t\tselector: RevokeSelector,\n\t\toptions: RevokeOptions,\n\t): Promise<number> {\n\t\treturn this.#db.transaction(() => {\n\t\t\tthis.#db\n\t\t\t\t.query(\n\t\t\t\t\t`INSERT INTO revocations (kind, id, at, keep_until) VALUES ($kind, $id, $at, $until)\n\t\t\t\t\tON CONFLICT (kind, id) DO UPDATE SET at = max(at, excluded.at),\n\t\t\t\t\tkeep_until = max(keep_until, excluded.keep_until)`,\n\t\t\t\t)\n\t\t\t\t.run({\n\t\t\t\t\tkind: \"grantId\" in selector ? \"grant\" : \"address\",\n\t\t\t\t\tid: \"grantId\" in selector ? selector.grantId : selector.addressId,\n\t\t\t\t\tat: options.now,\n\t\t\t\t\tuntil: options.keepUntil,\n\t\t\t\t});\n\t\t\treturn this.#delete(selector);\n\t\t})();\n\t}\n\n\t#delete(selector: RevokeSelector): number {\n\t\tconst result =\n\t\t\t\"grantId\" in selector\n\t\t\t\t? this.#db\n\t\t\t\t\t\t.query(\"DELETE FROM tokens WHERE grant_id = $id\")\n\t\t\t\t\t\t.run({ id: selector.grantId })\n\t\t\t\t: this.#db\n\t\t\t\t\t\t.query(\"DELETE FROM tokens WHERE address_id = $id\")\n\t\t\t\t\t\t.run({ id: selector.addressId });\n\t\treturn result.changes;\n\t}\n\n\tasync listGrants(addressId: string, now: number): Promise<GrantSummary[]> {\n\t\tconst rows = this.#db\n\t\t\t.query(\n\t\t\t\t`SELECT * FROM tokens WHERE address_id = $addressId AND expires_at > $now\n\t\t\t\tAND (kind = 'access' OR used_at IS NULL)`,\n\t\t\t)\n\t\t\t.all({ addressId, now }) as Row[];\n\t\treturn summarizeGrants(rows.map(toRecord), now);\n\t}\n\n\tasync deleteExpired(now: number): Promise<number> {\n\t\tthis.#db\n\t\t\t.query(\"DELETE FROM revocations WHERE keep_until <= $now\")\n\t\t\t.run({ now });\n\t\treturn this.#db\n\t\t\t.query(\"DELETE FROM tokens WHERE expires_at <= $now\")\n\t\t\t.run({ now }).changes;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.#db.close();\n\t}\n}\n",
|
|
20
|
-
"import type { Server, ServerWebSocket } from \"bun\";\nimport { version } from \"../package.json\" with { type: \"json\" };\nimport { addressIdFromSecret, isAddressId, shortAddress } from \"./address.ts\";\nimport {\n\tlargestMessageBytes,\n\ttype RelayConfig,\n\tresolveConfig,\n\ttype Site,\n\ttype StoreKind,\n\tsiteFor,\n} from \"./config.ts\";\nimport {\n\ttype Exchange,\n\tRelayErrorCode,\n\ttype RpcId,\n\trpcErrorBody,\n} from \"./exchange.ts\";\nimport { ipPrefixKey } from \"./ip.ts\";\nimport { createLogger, type Logger, truncateIp } from \"./log.ts\";\nimport {\n\tAuthorizationServer,\n\ttype AuthorizationTestMode,\n} from \"./oauth/server.ts\";\nimport {\n\tCloseCode,\n\ttype GrantInfo,\n\tMCP_PROTOCOL_VERSION,\n\tPROTOCOL_VERSION_META_KEY,\n\tSUBPROTOCOL,\n} from \"./protocol.ts\";\nimport { TabSession } from \"./session.ts\";\nimport { MemoryTokenStore } from \"./store/memory.ts\";\nimport { SqliteTokenStore } from \"./store/sqlite.ts\";\nimport type { TokenRecord, TokenStore } from \"./store/types.ts\";\nimport { hashToken } from \"./tokens.ts\";\n\nexport const VERSION: string = version;\n\n/** The one mismatched header Claude sends today (claude-code #93290, DEC-033). */\nconst CLAUDE_MISMATCHED_HEADER = \"2025-11-25\";\n\n/** Request headers forwarded to the tab (protocol: tunnelled MCP requests). */\nconst FORWARDED_HEADERS = new Set([\n\t\"content-type\",\n\t\"accept\",\n\t\"mcp-method\",\n\t\"mcp-name\",\n\t\"traceparent\",\n\t\"tracestate\",\n]);\n\nexport interface CreateRelayOptions\n\textends Omit<Partial<RelayConfig>, \"store\"> {\n\t/**\n\t * The token store: a `TokenStore` instance (e.g. Prisma, Redis), or the name\n\t * of a built-in one (`\"sqlite\"`, the default, at `sqlitePath`; `\"memory\"`).\n\t */\n\tstore?: StoreKind | TokenStore;\n\t/** Logger; defaults to JSON lines on stdout at `logLevel`. */\n\tlogger?: Logger;\n}\n\nexport interface Relay {\n\t/** The external origin (issuer and address base). */\n\treadonly url: string;\n\t/** The port the server listens on. */\n\treadonly port: number;\n\treadonly config: RelayConfig;\n\t/** The MCP address a page with this secret gets. */\n\taddressFor(secret: string): string;\n\t/** Number of connected tab sessions. */\n\treadonly sessionCount: number;\n\t/** Close all sessions (bye `shutdown`, close 4004) and stop the server. */\n\tstop(): Promise<void>;\n}\n\ninterface WsData {\n\tip: string;\n\torigin: string;\n\tsite: Site;\n\tsession?: TabSession;\n}\n\n/**\n * Test-only relaxations, never reachable from configuration or the package's\n * public API (`createTestRelay` is not exported from the package): CIMD\n * fetches from loopback test servers, shorter code lifetimes.\n */\nexport interface RelayTestHooks extends AuthorizationTestMode {\n\tpairingCodeTtlMs?: number;\n}\n\ninterface Body {\n\tvalue: Record<string, unknown>;\n\ttext: string;\n}\n\nfunction json(\n\tstatus: number,\n\tvalue: unknown,\n\theaders?: Record<string, string>,\n): Response {\n\tconst h = new Headers(headers);\n\th.set(\"content-type\", \"application/json\");\n\treturn new Response(JSON.stringify(value), { status, headers: h });\n}\n\nfunction rpcError(\n\tstatus: number,\n\trpcId: RpcId | undefined,\n\tcode: number,\n\tmessage: string,\n\theaders: Record<string, string>,\n\tdata?: unknown,\n): Response {\n\treturn new Response(rpcErrorBody(rpcId, code, message, data), {\n\t\tstatus,\n\t\theaders: { ...headers, \"content-type\": \"application/json\" },\n\t});\n}\n\nfunction rpcIdOf(body: Record<string, unknown>): RpcId | undefined {\n\tif (!(\"id\" in body)) return undefined;\n\tconst id = body[\"id\"];\n\treturn typeof id === \"string\" || typeof id === \"number\" ? id : null;\n}\n\n/** A loggable MCP method name (attacker-controlled input, so constrained). */\nfunction methodForLog(body: Record<string, unknown>): string {\n\tconst m = body[\"method\"];\n\treturn typeof m === \"string\" && /^[A-Za-z0-9_/.-]{1,64}$/.test(m) ? m : \"?\";\n}\n\nfunction metaVersion(body: Record<string, unknown>): unknown {\n\tconst params = body[\"params\"];\n\tif (typeof params !== \"object\" || params === null) return undefined;\n\tconst meta = (params as Record<string, unknown>)[\"_meta\"];\n\tif (typeof meta !== \"object\" || meta === null) return undefined;\n\treturn (meta as Record<string, unknown>)[PROTOCOL_VERSION_META_KEY];\n}\n\nconst INDEX_HTML = `<!doctype html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>tab-mcp relay</title></head>\n<body><h1>tab-mcp relay</h1>\n<p>This server relays AI apps' MCP requests to tools offered by web pages open in a browser tab.\nIt does not log request contents. Source and documentation:\n<a href=\"https://github.com/ractive/tab-mcp\">github.com/ractive/tab-mcp</a>.</p>\n</body></html>`;\n\n/** Start a relay. Returns once the server listens. */\nexport function createRelay(options: CreateRelayOptions = {}): Relay {\n\treturn startRelay(options, undefined);\n}\n\n/**\n * A relay with test hooks. Only for this repository's tests: it refuses to\n * start outside development and logs a warning.\n */\nexport function createTestRelay(\n\toptions: CreateRelayOptions,\n\thooks: RelayTestHooks,\n): Relay {\n\tif (options.development !== true) {\n\t\tthrow new Error(\"test hooks need development: true\");\n\t}\n\treturn startRelay(options, hooks);\n}\n\nfunction startRelay(\n\toptions: CreateRelayOptions,\n\thooks: RelayTestHooks | undefined,\n): Relay {\n\tconst { store: storeOption, logger: givenLogger, ...partial } = options;\n\tconst tokenStore = typeof storeOption === \"object\" ? storeOption : undefined;\n\tconst config = resolveConfig(\n\t\ttypeof storeOption === \"string\"\n\t\t\t? { ...partial, store: storeOption }\n\t\t\t: partial,\n\t);\n\tconst logger = givenLogger ?? createLogger(config.logLevel);\n\tconst ownsStore = tokenStore === undefined;\n\tconst store: TokenStore =\n\t\ttokenStore ??\n\t\t(config.store === \"sqlite\"\n\t\t\t? new SqliteTokenStore(config.sqlitePath)\n\t\t\t: new MemoryTokenStore());\n\n\tconst sessions = new Map<string, TabSession>();\n\tconst allSessions = new Set<TabSession>();\n\tconst perIp = new Map<string, number>();\n\tlet claudeWorkarounds = 0;\n\tlet publicUrl = config.publicUrl ?? \"\";\n\n\tconst corsHeaders: Record<string, string> = config.cors\n\t\t? {\n\t\t\t\t\"access-control-allow-origin\": \"*\",\n\t\t\t\t\"access-control-expose-headers\":\n\t\t\t\t\t\"www-authenticate, mcp-protocol-version\",\n\t\t\t}\n\t\t: {};\n\n\t/** Tombstones outlive every token issued before the revocation (DEC-063). */\n\tconst revokeOptions = () => {\n\t\tconst now = Date.now();\n\t\treturn { now, keepUntil: now + config.grantLifetimeMs };\n\t};\n\n\tfunction grantRemoved(\n\t\taddressId: string,\n\t\tgrantId: string,\n\t\treason: \"revoked\" | \"reuse_detected\" | \"expired\",\n\t): void {\n\t\tconst session = sessions.get(addressId);\n\t\tif (session?.ready)\n\t\t\tsession.send({ type: \"grant.removed\", grantId, reason });\n\t}\n\n\tconst host = {\n\t\tconfig,\n\t\tlogger,\n\t\tstore,\n\t\t...(hooks?.pairingCodeTtlMs === undefined\n\t\t\t? {}\n\t\t\t: { pairingCodeTtlMs: hooks.pairingCodeTtlMs }),\n\t\tpublicUrl: () => publicUrl,\n\t\tasync revokeGrant(session: TabSession, grantId: string): Promise<boolean> {\n\t\t\tconst addressId = session.addressId;\n\t\t\tif (addressId === undefined) return false;\n\t\t\tconst grants = await store.listGrants(addressId, Date.now());\n\t\t\tif (!grants.some((g) => g.grantId === grantId)) return false;\n\t\t\tawait store.revoke({ grantId }, revokeOptions());\n\t\t\tlogger.info(\"oauth.revoked\", {\n\t\t\t\taddress: shortAddress(addressId),\n\t\t\t\tby: \"tab\",\n\t\t\t});\n\t\t\tgrantRemoved(addressId, grantId, \"revoked\");\n\t\t\treturn true;\n\t\t},\n\t\tasync revokeAll(session: TabSession): Promise<void> {\n\t\t\tconst addressId = session.addressId;\n\t\t\tif (addressId === undefined) return;\n\t\t\tconst grants = await store.listGrants(addressId, Date.now());\n\t\t\tawait store.revoke({ addressId }, revokeOptions());\n\t\t\tlogger.info(\"oauth.revoked_all\", {\n\t\t\t\taddress: shortAddress(addressId),\n\t\t\t\tgrants: grants.length,\n\t\t\t});\n\t\t\tfor (const g of grants) grantRemoved(addressId, g.grantId, \"revoked\");\n\t\t},\n\t\tclaimAddress(session: TabSession): TabSession | undefined {\n\t\t\tconst id = session.addressId;\n\t\t\tif (id === undefined) return undefined;\n\t\t\tconst previous = sessions.get(id);\n\t\t\tsessions.set(id, session);\n\t\t\treturn previous === session ? undefined : previous;\n\t\t},\n\t\treleased(session: TabSession): void {\n\t\t\tallSessions.delete(session);\n\t\t\tif (\n\t\t\t\tsession.addressId !== undefined &&\n\t\t\t\tsessions.get(session.addressId) === session\n\t\t\t) {\n\t\t\t\tsessions.delete(session.addressId);\n\t\t\t}\n\t\t\treleaseIp(session.ip);\n\t\t},\n\t};\n\n\tfunction releaseIp(ip: string): void {\n\t\tconst n = (perIp.get(ip) ?? 1) - 1;\n\t\tif (n <= 0) perIp.delete(ip);\n\t\telse perIp.set(ip, n);\n\t}\n\n\tfunction clientIp(req: Request, server: Server<WsData>): string {\n\t\tif (config.trustProxy === \"x-real-ip\") {\n\t\t\tconst v = req.headers.get(\"x-real-ip\")?.trim();\n\t\t\tif (v) return v;\n\t\t} else if (config.trustProxy === \"x-forwarded-for\") {\n\t\t\tconst parts = (req.headers.get(\"x-forwarded-for\") ?? \"\")\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((s) => s !== \"\");\n\t\t\tconst last = parts.at(-1);\n\t\t\tif (last !== undefined) return last;\n\t\t}\n\t\treturn server.requestIP(req)?.address ?? \"unknown\";\n\t}\n\n\tconst auth = new AuthorizationServer(\n\t\t{\n\t\t\tconfig,\n\t\t\tlogger,\n\t\t\tstore,\n\t\t\tpublicUrl: () => publicUrl,\n\t\t\tsession: (addressId) => {\n\t\t\t\tconst s = sessions.get(addressId);\n\t\t\t\treturn s?.ready === true ? s : undefined;\n\t\t\t},\n\t\t\tgrantAdded: (addressId: string, grant: GrantInfo) => {\n\t\t\t\tconst session = sessions.get(addressId);\n\t\t\t\tif (session?.ready) session.send({ type: \"grant.added\", grant });\n\t\t\t},\n\t\t\tgrantRemoved: (addressId, grantId, reason) =>\n\t\t\t\tgrantRemoved(\n\t\t\t\t\taddressId,\n\t\t\t\t\tgrantId,\n\t\t\t\t\treason as \"revoked\" | \"reuse_detected\" | \"expired\",\n\t\t\t\t),\n\t\t},\n\t\thooks,\n\t);\n\tif (hooks !== undefined) {\n\t\tlogger.warn(\"relay.test_hooks\", {\n\t\t\tmessage: \"test hooks are on: never use this relay outside tests\",\n\t\t});\n\t}\n\n\tfunction handleTab(\n\t\treq: Request,\n\t\tserver: Server<WsData>,\n\t): Response | undefined {\n\t\tconst origin = req.headers.get(\"origin\");\n\t\tconst site = siteFor(config, origin);\n\t\tif (site === undefined) {\n\t\t\tlogger.info(\"tab.refused\", { reason: \"origin\" });\n\t\t\treturn json(403, { error: \"origin_not_allowed\" });\n\t\t}\n\t\tconst offered = (req.headers.get(\"sec-websocket-protocol\") ?? \"\")\n\t\t\t.split(\",\")\n\t\t\t.map((s) => s.trim());\n\t\tif (!offered.includes(SUBPROTOCOL)) {\n\t\t\treturn json(426, {\n\t\t\t\terror: \"unsupported_protocol\",\n\t\t\t\tsupported: [SUBPROTOCOL],\n\t\t\t});\n\t\t}\n\t\tconst realIp = clientIp(req, server);\n\t\t// Counted per /64 for IPv6 (DEC-061): one subscriber owns a whole /64.\n\t\tconst ip = ipPrefixKey(realIp);\n\t\tif (allSessions.size >= config.maxSessions) {\n\t\t\tlogger.warn(\"tab.refused\", { reason: \"max_sessions\" });\n\t\t\treturn json(429, { error: \"too_many_sessions\" });\n\t\t}\n\t\tconst count = perIp.get(ip) ?? 0;\n\t\tif (count >= config.maxSessionsPerIp) {\n\t\t\tlogger.warn(\"tab.refused\", {\n\t\t\t\treason: \"max_sessions_per_ip\",\n\t\t\t\tip: truncateIp(realIp),\n\t\t\t});\n\t\t\treturn json(429, { error: \"too_many_sessions\" });\n\t\t}\n\t\tperIp.set(ip, count + 1);\n\t\tconst ok = server.upgrade(req, {\n\t\t\tdata: { ip, origin: origin ?? \"\", site },\n\t\t\theaders: { \"Sec-WebSocket-Protocol\": SUBPROTOCOL },\n\t\t});\n\t\tif (ok) return undefined;\n\t\treleaseIp(ip);\n\t\treturn json(400, { error: \"websocket_upgrade_expected\" });\n\t}\n\n\tfunction wwwAuthenticate(id: string, presented: boolean): string {\n\t\tconst metadata = `${publicUrl}/.well-known/oauth-protected-resource/a/${id}/mcp`;\n\t\tconst error = presented ? ', error=\"invalid_token\"' : \"\";\n\t\treturn `Bearer resource_metadata=\"${metadata}\", scope=\"tools\"${error}`;\n\t}\n\n\tasync function authenticate(\n\t\treq: Request,\n\t\taddressId: string,\n\t): Promise<TokenRecord | \"missing\" | \"invalid\" | \"unavailable\"> {\n\t\tconst header = req.headers.get(\"authorization\");\n\t\tif (header === null) return \"missing\";\n\t\tconst match = /^Bearer ([A-Za-z0-9._~+/-]+=*)$/i.exec(header.trim());\n\t\tconst token = match?.[1];\n\t\tif (token === undefined) return \"invalid\";\n\t\tlet record: TokenRecord | undefined;\n\t\ttry {\n\t\t\trecord = await store.get(hashToken(token));\n\t\t} catch (error) {\n\t\t\tlogger.error(\"store.error\", {\n\t\t\t\top: \"get\",\n\t\t\t\tmessage: error instanceof Error ? error.message : \"unknown\",\n\t\t\t});\n\t\t\treturn \"unavailable\";\n\t\t}\n\t\tif (\n\t\t\trecord === undefined ||\n\t\t\trecord.kind !== \"access\" ||\n\t\t\trecord.addressId !== addressId ||\n\t\t\trecord.expiresAt <= Date.now() ||\n\t\t\t!record.scopes.includes(\"tools\")\n\t\t) {\n\t\t\treturn \"invalid\";\n\t\t}\n\t\treturn record;\n\t}\n\n\tasync function readBody(\n\t\treq: Request,\n\t\tmaxBytes: number,\n\t): Promise<Body | Response> {\n\t\tconst length = Number(req.headers.get(\"content-length\") ?? \"0\");\n\t\tif (length > maxBytes) {\n\t\t\treturn rpcError(\n\t\t\t\t413,\n\t\t\t\tundefined,\n\t\t\t\t-32600,\n\t\t\t\t\"Request body too large.\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\tlet bytes: ArrayBuffer;\n\t\ttry {\n\t\t\t// Bun's idle timeout does not fire while a body is being read, so a\n\t\t\t// client that stalls mid-body would hold the socket; our own deadline\n\t\t\t// answers 408 and closes the connection.\n\t\t\tconst reading = req.arrayBuffer();\n\t\t\treading.catch(() => {}); // rejects once the socket is closed\n\t\t\tlet timer: Timer | undefined;\n\t\t\tconst deadline = new Promise<\"timeout\">((resolve) => {\n\t\t\t\ttimer = setTimeout(() => resolve(\"timeout\"), config.bodyTimeoutMs);\n\t\t\t});\n\t\t\tconst result = await Promise.race([reading, deadline]);\n\t\t\tclearTimeout(timer);\n\t\t\tif (result === \"timeout\") {\n\t\t\t\treturn rpcError(\n\t\t\t\t\t408,\n\t\t\t\t\tundefined,\n\t\t\t\t\t-32600,\n\t\t\t\t\t\"The request body did not arrive in time.\",\n\t\t\t\t\t{ ...corsHeaders, connection: \"close\" },\n\t\t\t\t);\n\t\t\t}\n\t\t\tbytes = result;\n\t\t} catch {\n\t\t\treturn rpcError(\n\t\t\t\t400,\n\t\t\t\tundefined,\n\t\t\t\t-32700,\n\t\t\t\t\"Could not read the request body.\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\tif (bytes.byteLength > maxBytes) {\n\t\t\treturn rpcError(\n\t\t\t\t413,\n\t\t\t\tundefined,\n\t\t\t\t-32600,\n\t\t\t\t\"Request body too large.\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\tlet text: string;\n\t\tlet value: unknown;\n\t\ttry {\n\t\t\ttext = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n\t\t\tvalue = JSON.parse(text);\n\t\t} catch {\n\t\t\treturn rpcError(400, undefined, -32700, \"Parse error.\", corsHeaders);\n\t\t}\n\t\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\t\treturn rpcError(\n\t\t\t\t400,\n\t\t\t\tundefined,\n\t\t\t\t-32600,\n\t\t\t\t\"The body must be one JSON-RPC message (no batches).\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\treturn { value: value as Record<string, unknown>, text };\n\t}\n\n\t/** DEC-033 / DEC-040: the protocol-version pre-check. */\n\tfunction checkVersion(\n\t\treq: Request,\n\t\tbody: Record<string, unknown>,\n\t\trpcId: RpcId | undefined,\n\t): Response | { forwardVersion: string } {\n\t\tconst header = req.headers.get(\"mcp-protocol-version\");\n\t\tif (body[\"method\"] === \"initialize\") {\n\t\t\tconst params = body[\"params\"] as Record<string, unknown> | undefined;\n\t\t\tconst requested =\n\t\t\t\ttypeof params?.[\"protocolVersion\"] === \"string\"\n\t\t\t\t\t? params[\"protocolVersion\"]\n\t\t\t\t\t: (header ?? null);\n\t\t\treturn rpcError(\n\t\t\t\t400,\n\t\t\t\trpcId,\n\t\t\t\t-32022,\n\t\t\t\t`Unsupported protocol version: ${String(requested)}. This server supports only ${MCP_PROTOCOL_VERSION}.`,\n\t\t\t\tcorsHeaders,\n\t\t\t\t{ supported: [MCP_PROTOCOL_VERSION], requested },\n\t\t\t);\n\t\t}\n\t\tif (header === MCP_PROTOCOL_VERSION) return { forwardVersion: header };\n\t\tif (\n\t\t\theader === CLAUDE_MISMATCHED_HEADER &&\n\t\t\tmetaVersion(body) === MCP_PROTOCOL_VERSION\n\t\t) {\n\t\t\t// Logged once per process; the running count is in /healthz.\n\t\t\tif (++claudeWorkarounds === 1) {\n\t\t\t\tlogger.info(\"mcp.claude_header_workaround\", {\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"accepting MCP-Protocol-Version 2025-11-25 with a 2026-07-28 body (claude-code #93290); counted in /healthz\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { forwardVersion: MCP_PROTOCOL_VERSION };\n\t\t}\n\t\tif (header === null) {\n\t\t\treturn rpcError(\n\t\t\t\t400,\n\t\t\t\trpcId,\n\t\t\t\t-32020,\n\t\t\t\t\"Missing MCP-Protocol-Version header.\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\treturn rpcError(\n\t\t\t400,\n\t\t\trpcId,\n\t\t\t-32022,\n\t\t\t`Unsupported protocol version: ${header}. This server supports only ${MCP_PROTOCOL_VERSION}.`,\n\t\t\tcorsHeaders,\n\t\t\t{ supported: [MCP_PROTOCOL_VERSION], requested: header },\n\t\t);\n\t}\n\n\tasync function handleMcp(\n\t\treq: Request,\n\t\tserver: Server<WsData>,\n\t\taddressId: string,\n\t): Promise<Response> {\n\t\tconst started = Date.now();\n\t\tconst logDone = (\n\t\t\tstatus: number,\n\t\t\tmethod: string,\n\t\t\textra: Record<string, string | number> = {},\n\t\t) =>\n\t\t\tlogger.info(\"mcp.request\", {\n\t\t\t\taddress: shortAddress(addressId),\n\t\t\t\tmethod,\n\t\t\t\tstatus,\n\t\t\t\tdurationMs: Date.now() - started,\n\t\t\t\t...extra,\n\t\t\t});\n\n\t\t// The page's own limit when it is connected; else the instance's (the\n\t\t// request then ends with 401 or 503 anyway).\n\t\tconst body = await readBody(\n\t\t\treq,\n\t\t\tsessions.get(addressId)?.limits.maxMessageBytes ?? config.maxMessageBytes,\n\t\t);\n\t\tif (body instanceof Response) {\n\t\t\tlogDone(body.status, \"?\");\n\t\t\treturn body;\n\t\t}\n\t\tconst rpcId = rpcIdOf(body.value);\n\t\tconst method = methodForLog(body.value);\n\n\t\tconst version = checkVersion(req, body.value, rpcId);\n\t\tif (version instanceof Response) {\n\t\t\tlogDone(version.status, method);\n\t\t\treturn version;\n\t\t}\n\n\t\tconst auth = await authenticate(req, addressId);\n\t\tif (auth === \"unavailable\") {\n\t\t\t// Not the token's fault: a 401 would make clients drop valid tokens.\n\t\t\tlogDone(503, method, { reason: \"store_unavailable\" });\n\t\t\treturn rpcError(\n\t\t\t\t503,\n\t\t\t\trpcId,\n\t\t\t\tRelayErrorCode.storeUnavailable,\n\t\t\t\t\"The relay cannot check tokens right now. Try again shortly.\",\n\t\t\t\t{ ...corsHeaders, \"retry-after\": \"5\" },\n\t\t\t);\n\t\t}\n\t\tif (typeof auth === \"string\") {\n\t\t\tlogDone(401, method);\n\t\t\treturn json(\n\t\t\t\t401,\n\t\t\t\t{\n\t\t\t\t\terror: \"invalid_token\",\n\t\t\t\t\terror_description:\n\t\t\t\t\t\tauth === \"missing\"\n\t\t\t\t\t\t\t? \"Authorization required.\"\n\t\t\t\t\t\t\t: \"The access token is not valid.\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t...corsHeaders,\n\t\t\t\t\t\"www-authenticate\": wwwAuthenticate(addressId, auth === \"invalid\"),\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\tconst session = sessions.get(addressId);\n\t\tif (session === undefined || !session.ready) {\n\t\t\tlogDone(503, method, { reason: \"page_not_open\" });\n\t\t\treturn rpcError(\n\t\t\t\t503,\n\t\t\t\trpcId,\n\t\t\t\tRelayErrorCode.pageNotOpen,\n\t\t\t\t'The page is not open. Open the web page that offers these tools and click \"Connect your AI tool\".',\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\tif (session.pending.size >= session.limits.maxConcurrentRequests) {\n\t\t\tlogDone(429, method);\n\t\t\treturn rpcError(\n\t\t\t\t429,\n\t\t\t\trpcId,\n\t\t\t\tRelayErrorCode.overloaded,\n\t\t\t\t\"Too many requests at once for this page.\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tfor (const [k, v] of req.headers) {\n\t\t\tconst key = k.toLowerCase();\n\t\t\tif (FORWARDED_HEADERS.has(key) || key.startsWith(\"mcp-param-\"))\n\t\t\t\theaders[key] = v;\n\t\t}\n\t\theaders[\"mcp-protocol-version\"] = version.forwardVersion;\n\n\t\tconst clientHostName = (() => {\n\t\t\ttry {\n\t\t\t\treturn new URL(auth.clientId).host;\n\t\t\t} catch {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t})();\n\t\t// The AI app may have gone while the body was read or the token checked:\n\t\t// then forward nothing (the abort event has already fired and would not\n\t\t// cancel the exchange, which would hold a slot until the timeout).\n\t\tif (req.signal.aborted) {\n\t\t\tlogDone(499, method, { outcome: \"client_closed\" });\n\t\t\treturn new Response(null, { status: 499 });\n\t\t}\n\t\t// Only now, for an authenticated request that is about to be forwarded,\n\t\t// switch off Bun's idle timer: our own request timer and keep-alives take\n\t\t// over (Bun research, finding 1). Body reading and every unauthenticated\n\t\t// path keep the idle timeout, so a stalled client cannot hold a socket.\n\t\tserver.timeout(req, 0);\n\t\tconst exchange = session.forward({\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: body.text,\n\t\t\trpcId,\n\t\t\tisListen: body.value[\"method\"] === \"subscriptions/listen\",\n\t\t\tgrant: {\n\t\t\t\tgrantId: auth.grantId,\n\t\t\t\tclientId: auth.clientId,\n\t\t\t\tscopes: auth.scopes,\n\t\t\t},\n\t\t\textraHeaders: corsHeaders,\n\t\t\tonDone: (e: Exchange) =>\n\t\t\t\tlogDone(e.status, method, {\n\t\t\t\t\tsession: session.sessionId,\n\t\t\t\t\tclient: clientHostName,\n\t\t\t\t\toutcome: e.outcome,\n\t\t\t\t}),\n\t\t});\n\t\treq.signal.addEventListener(\"abort\", () => exchange.clientClosed(), {\n\t\t\tonce: true,\n\t\t});\n\t\treturn exchange.response;\n\t}\n\n\tfunction preflight(req: Request): Response {\n\t\tif (!config.cors)\n\t\t\treturn new Response(null, { status: 405, headers: { allow: \"POST\" } });\n\t\tconst requested = req.headers.get(\"access-control-request-headers\") ?? \"\";\n\t\treturn new Response(null, {\n\t\t\tstatus: 204,\n\t\t\theaders: {\n\t\t\t\t...corsHeaders,\n\t\t\t\t\"access-control-allow-methods\": \"POST, OPTIONS\",\n\t\t\t\t\"access-control-allow-headers\":\n\t\t\t\t\trequested !== \"\"\n\t\t\t\t\t\t? requested\n\t\t\t\t\t\t: \"authorization, content-type, accept, mcp-protocol-version, mcp-method, mcp-name\",\n\t\t\t\t\"access-control-max-age\": \"600\",\n\t\t\t},\n\t\t});\n\t}\n\n\tconst methodNotAllowed = () =>\n\t\tnew Response(null, {\n\t\t\tstatus: 405,\n\t\t\theaders: { ...corsHeaders, allow: \"POST\" },\n\t\t});\n\n\tconst postOnly = () =>\n\t\tnew Response(null, { status: 405, headers: { allow: \"POST, OPTIONS\" } });\n\tconst largest = largestMessageBytes(config);\n\tconst ipOf = (req: Request, srv: Server<WsData>) =>\n\t\tipPrefixKey(clientIp(req, srv));\n\tconst server = Bun.serve({\n\t\tport: config.port,\n\t\thostname: config.host,\n\t\tdevelopment: false,\n\t\tmaxRequestBodySize: largest + 1024,\n\t\tidleTimeout: config.httpIdleTimeoutS,\n\t\troutes: {\n\t\t\t\"/healthz\": {\n\t\t\t\tGET: () =>\n\t\t\t\t\tjson(200, {\n\t\t\t\t\t\tstatus: \"ok\",\n\t\t\t\t\t\tversion: VERSION,\n\t\t\t\t\t\tcounters: { claudeHeaderWorkaround: claudeWorkarounds },\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\t\"/\": {\n\t\t\t\tGET: () =>\n\t\t\t\t\tnew Response(INDEX_HTML, {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"content-type\": \"text/html; charset=utf-8\",\n\t\t\t\t\t\t\t\"content-security-policy\":\n\t\t\t\t\t\t\t\t\"default-src 'none'; frame-ancestors 'none'\",\n\t\t\t\t\t\t\t\"x-content-type-options\": \"nosniff\",\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\t\"/tab\": (req, srv) => handleTab(req, srv),\n\t\t\t\"/.well-known/oauth-authorization-server\": {\n\t\t\t\tGET: () => auth.metadata(),\n\t\t\t\tOPTIONS: () => auth.preflight(\"GET\"),\n\t\t\t},\n\t\t\t\"/.well-known/oauth-protected-resource/a/:id/mcp\": {\n\t\t\t\tGET: (req) => auth.protectedResource(req.params.id),\n\t\t\t\tOPTIONS: () => auth.preflight(\"GET\"),\n\t\t\t},\n\t\t\t\"/authorize\": {\n\t\t\t\tGET: (req, srv) => auth.authorize(req, ipOf(req, srv)),\n\t\t\t\tPOST: (req, srv) => auth.authorizeSubmit(req, ipOf(req, srv)),\n\t\t\t},\n\t\t\t\"/authorize.css\": { GET: () => auth.stylesheet() },\n\t\t\t\"/token\": {\n\t\t\t\tPOST: (req, srv) => auth.token(req, ipOf(req, srv)),\n\t\t\t\tOPTIONS: () => auth.preflight(\"POST\"),\n\t\t\t\tGET: postOnly,\n\t\t\t},\n\t\t\t\"/revoke\": {\n\t\t\t\tPOST: (req, srv) => auth.revoke(req, ipOf(req, srv)),\n\t\t\t\tOPTIONS: () => auth.preflight(\"POST\"),\n\t\t\t\tGET: postOnly,\n\t\t\t},\n\t\t\t\"/a/:id/mcp\": {\n\t\t\t\tPOST: (req, srv) => {\n\t\t\t\t\tconst id = req.params.id;\n\t\t\t\t\tif (!isAddressId(id))\n\t\t\t\t\t\treturn new Response(\"Not found\", { status: 404 });\n\t\t\t\t\treturn handleMcp(req, srv, id);\n\t\t\t\t},\n\t\t\t\tOPTIONS: (req) => preflight(req),\n\t\t\t\tGET: methodNotAllowed,\n\t\t\t\tDELETE: methodNotAllowed,\n\t\t\t\tPUT: methodNotAllowed,\n\t\t\t\tPATCH: methodNotAllowed,\n\t\t\t},\n\t\t},\n\t\tfetch: () => new Response(\"Not found\", { status: 404 }),\n\t\twebsocket: {\n\t\t\tdata: {} as WsData,\n\t\t\tmaxPayloadLength: largest * 4,\n\t\t\tbackpressureLimit: config.backpressureLimitBytes,\n\t\t\tcloseOnBackpressureLimit: false,\n\t\t\tidleTimeout: 120,\n\t\t\tsendPings: true,\n\t\t\tperMessageDeflate: false,\n\t\t\topen(ws: ServerWebSocket<WsData>) {\n\t\t\t\tconst session = new TabSession(\n\t\t\t\t\tws,\n\t\t\t\t\tws.data.ip,\n\t\t\t\t\tws.data.origin,\n\t\t\t\t\tws.data.site,\n\t\t\t\t\thost,\n\t\t\t\t);\n\t\t\t\tws.data.session = session;\n\t\t\t\tallSessions.add(session);\n\t\t\t},\n\t\t\tmessage(ws: ServerWebSocket<WsData>, message: string | Buffer) {\n\t\t\t\tws.data.session?.handleFrame(\n\t\t\t\t\ttypeof message === \"string\" ? message : new Uint8Array(message),\n\t\t\t\t);\n\t\t\t},\n\t\t\tclose(ws: ServerWebSocket<WsData>, code: number) {\n\t\t\t\tws.data.session?.closed(code);\n\t\t\t},\n\t\t},\n\t});\n\n\tconst port = server.port ?? config.port;\n\tif (publicUrl === \"\") publicUrl = `http://localhost:${port}`;\n\n\tconst sweep = setInterval(() => {\n\t\tauth.sweep();\n\t\tstore\n\t\t\t.deleteExpired(Date.now())\n\t\t\t.then((n) => {\n\t\t\t\tif (n > 0) logger.debug(\"store.swept\", { deleted: n });\n\t\t\t})\n\t\t\t.catch((error: unknown) =>\n\t\t\t\tlogger.error(\"store.error\", {\n\t\t\t\t\top: \"deleteExpired\",\n\t\t\t\t\tmessage: error instanceof Error ? error.message : \"unknown\",\n\t\t\t\t}),\n\t\t\t);\n\t}, config.sweepIntervalMs);\n\n\tconst siteCount =\n\t\tconfig.allowedOrigins === \"*\"\n\t\t\t? \"*\"\n\t\t\t: config.allowedOrigins.length + config.sites.length;\n\tif (config.allowedOrigins === \"*\") {\n\t\tlogger.warn(\"relay.open_relay\", {\n\t\t\tmessage:\n\t\t\t\t\"TAB_MCP_ALLOWED_ORIGINS=* lets any website open tab sessions on this relay\",\n\t\t});\n\t} else if (siteCount === 0) {\n\t\tlogger.warn(\"relay.no_origins\", {\n\t\t\tmessage:\n\t\t\t\t\"TAB_MCP_ALLOWED_ORIGINS and TAB_MCP_SITES are empty: no page can connect\",\n\t\t});\n\t}\n\tlogger.info(\"relay.start\", {\n\t\tversion: VERSION,\n\t\turl: publicUrl,\n\t\tport,\n\t\tstore: ownsStore ? config.store : \"custom\",\n\t\torigins: siteCount,\n\t});\n\n\tlet stopping: Promise<void> | undefined;\n\treturn {\n\t\turl: publicUrl,\n\t\tport,\n\t\tconfig,\n\t\taddressFor: (secret) => `${publicUrl}/a/${addressIdFromSecret(secret)}/mcp`,\n\t\tget sessionCount() {\n\t\t\treturn allSessions.size;\n\t\t},\n\t\tstop() {\n\t\t\tstopping ??= (async () => {\n\t\t\t\tclearInterval(sweep);\n\t\t\t\tfor (const session of [...allSessions]) {\n\t\t\t\t\tsession.end(\n\t\t\t\t\t\tCloseCode.shuttingDown,\n\t\t\t\t\t\t\"relay shutting down\",\n\t\t\t\t\t\t\"shutdown\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait Bun.sleep(20); // let close frames leave\n\t\t\t\tawait server.stop(true);\n\t\t\t\tif (ownsStore) await store.close?.();\n\t\t\t\tlogger.info(\"relay.stop\", {});\n\t\t\t})();\n\t\t\treturn stopping;\n\t\t},\n\t};\n}\n"
|
|
20
|
+
"import type { Server, ServerWebSocket } from \"bun\";\nimport { version } from \"../package.json\" with { type: \"json\" };\nimport { addressIdFromSecret, isAddressId, shortAddress } from \"./address.ts\";\nimport {\n\tlargestMessageBytes,\n\ttype RelayConfig,\n\tresolveConfig,\n\ttype Site,\n\ttype StoreKind,\n\tsiteFor,\n} from \"./config.ts\";\nimport {\n\ttype Exchange,\n\tRelayErrorCode,\n\ttype RpcId,\n\trpcErrorBody,\n} from \"./exchange.ts\";\nimport { ipPrefixKey } from \"./ip.ts\";\nimport { createLogger, type Logger, truncateIp } from \"./log.ts\";\nimport {\n\tAuthorizationServer,\n\ttype AuthorizationTestMode,\n} from \"./oauth/server.ts\";\nimport {\n\tCloseCode,\n\ttype GrantInfo,\n\tMCP_PROTOCOL_VERSION,\n\tPROTOCOL_VERSION_META_KEY,\n\tSUBPROTOCOL,\n} from \"./protocol.ts\";\nimport { TabSession } from \"./session.ts\";\nimport { MemoryTokenStore } from \"./store/memory.ts\";\nimport { SqliteTokenStore } from \"./store/sqlite.ts\";\nimport type { TokenRecord, TokenStore } from \"./store/types.ts\";\nimport { hashToken } from \"./tokens.ts\";\n\nexport const VERSION: string = version;\n\n/** The one mismatched header Claude sends today (claude-code #93290, DEC-033). */\nconst CLAUDE_MISMATCHED_HEADER = \"2025-11-25\";\n\n/** Request headers forwarded to the tab (protocol: tunnelled MCP requests). */\nconst FORWARDED_HEADERS = new Set([\n\t\"content-type\",\n\t\"accept\",\n\t\"mcp-method\",\n\t\"mcp-name\",\n\t\"traceparent\",\n\t\"tracestate\",\n]);\n\nexport interface CreateRelayOptions\n\textends Omit<Partial<RelayConfig>, \"store\"> {\n\t/**\n\t * The token store: a `TokenStore` instance (e.g. Prisma, Redis), or the name\n\t * of a built-in one (`\"sqlite\"`, the default, at `sqlitePath`; `\"memory\"`).\n\t */\n\tstore?: StoreKind | TokenStore;\n\t/** Logger; defaults to JSON lines on stdout at `logLevel`. */\n\tlogger?: Logger;\n}\n\nexport interface Relay {\n\t/** The external origin (issuer and address base). */\n\treadonly url: string;\n\t/** The port the server listens on. */\n\treadonly port: number;\n\treadonly config: RelayConfig;\n\t/** The MCP address a page with this secret gets. */\n\taddressFor(secret: string): string;\n\t/** Number of connected tab sessions. */\n\treadonly sessionCount: number;\n\t/** Close all sessions (bye `shutdown`, close 4004) and stop the server. */\n\tstop(): Promise<void>;\n}\n\ninterface WsData {\n\tip: string;\n\torigin: string;\n\tsite: Site;\n\tsession?: TabSession;\n}\n\n/**\n * Test-only relaxations, never reachable from configuration or the package's\n * public API (`createTestRelay` is not exported from the package): CIMD\n * fetches from loopback test servers, shorter code lifetimes.\n */\nexport interface RelayTestHooks extends AuthorizationTestMode {\n\tpairingCodeTtlMs?: number;\n}\n\ninterface Body {\n\tvalue: Record<string, unknown>;\n\ttext: string;\n}\n\nfunction json(\n\tstatus: number,\n\tvalue: unknown,\n\theaders?: Record<string, string>,\n): Response {\n\tconst h = new Headers(headers);\n\th.set(\"content-type\", \"application/json\");\n\treturn new Response(JSON.stringify(value), { status, headers: h });\n}\n\nfunction rpcError(\n\tstatus: number,\n\trpcId: RpcId | undefined,\n\tcode: number,\n\tmessage: string,\n\theaders: Record<string, string>,\n\tdata?: unknown,\n): Response {\n\treturn new Response(rpcErrorBody(rpcId, code, message, data), {\n\t\tstatus,\n\t\theaders: { ...headers, \"content-type\": \"application/json\" },\n\t});\n}\n\nfunction rpcIdOf(body: Record<string, unknown>): RpcId | undefined {\n\tif (!(\"id\" in body)) return undefined;\n\tconst id = body[\"id\"];\n\treturn typeof id === \"string\" || typeof id === \"number\" ? id : null;\n}\n\n/** A loggable MCP method name (attacker-controlled input, so constrained). */\nfunction methodForLog(body: Record<string, unknown>): string {\n\tconst m = body[\"method\"];\n\treturn typeof m === \"string\" && /^[A-Za-z0-9_/.-]{1,64}$/.test(m) ? m : \"?\";\n}\n\nfunction metaVersion(body: Record<string, unknown>): unknown {\n\tconst params = body[\"params\"];\n\tif (typeof params !== \"object\" || params === null) return undefined;\n\tconst meta = (params as Record<string, unknown>)[\"_meta\"];\n\tif (typeof meta !== \"object\" || meta === null) return undefined;\n\treturn (meta as Record<string, unknown>)[PROTOCOL_VERSION_META_KEY];\n}\n\nconst INDEX_HTML = `<!doctype html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>tab-mcp relay</title></head>\n<body><h1>tab-mcp relay</h1>\n<p>This server relays AI apps' MCP requests to tools offered by web pages open in a browser tab.\nIt does not log request contents. Source and documentation:\n<a href=\"https://github.com/ractive/tab-mcp\">github.com/ractive/tab-mcp</a>.</p>\n</body></html>`;\n\n/** Start a relay. Returns once the server listens. */\nexport function createRelay(options: CreateRelayOptions = {}): Relay {\n\treturn startRelay(options, undefined);\n}\n\n/**\n * A relay with test hooks. Only for this repository's tests: it refuses to\n * start outside development and logs a warning.\n */\nexport function createTestRelay(\n\toptions: CreateRelayOptions,\n\thooks: RelayTestHooks,\n): Relay {\n\tif (options.development !== true) {\n\t\tthrow new Error(\"test hooks need development: true\");\n\t}\n\treturn startRelay(options, hooks);\n}\n\nfunction startRelay(\n\toptions: CreateRelayOptions,\n\thooks: RelayTestHooks | undefined,\n): Relay {\n\tconst { store: storeOption, logger: givenLogger, ...partial } = options;\n\tconst tokenStore = typeof storeOption === \"object\" ? storeOption : undefined;\n\tconst config = resolveConfig(\n\t\ttypeof storeOption === \"string\"\n\t\t\t? { ...partial, store: storeOption }\n\t\t\t: partial,\n\t);\n\tconst logger = givenLogger ?? createLogger(config.logLevel);\n\tconst ownsStore = tokenStore === undefined;\n\tconst store: TokenStore =\n\t\ttokenStore ??\n\t\t(config.store === \"sqlite\"\n\t\t\t? new SqliteTokenStore(config.sqlitePath)\n\t\t\t: new MemoryTokenStore());\n\n\tconst sessions = new Map<string, TabSession>();\n\tconst allSessions = new Set<TabSession>();\n\tconst perIp = new Map<string, number>();\n\tlet claudeWorkarounds = 0;\n\tlet publicUrl = config.publicUrl ?? \"\";\n\n\tconst corsHeaders: Record<string, string> = config.cors\n\t\t? {\n\t\t\t\t\"access-control-allow-origin\": \"*\",\n\t\t\t\t\"access-control-expose-headers\":\n\t\t\t\t\t\"www-authenticate, mcp-protocol-version\",\n\t\t\t}\n\t\t: {};\n\n\t/** Tombstones outlive every token issued before the revocation (DEC-063). */\n\tconst revokeOptions = () => {\n\t\tconst now = Date.now();\n\t\treturn { now, keepUntil: now + config.grantLifetimeMs };\n\t};\n\n\tfunction grantRemoved(\n\t\taddressId: string,\n\t\tgrantId: string,\n\t\treason: \"revoked\" | \"reuse_detected\" | \"expired\",\n\t): void {\n\t\tconst session = sessions.get(addressId);\n\t\tif (session?.ready)\n\t\t\tsession.send({ type: \"grant.removed\", grantId, reason });\n\t}\n\n\tconst host = {\n\t\tconfig,\n\t\tlogger,\n\t\tstore,\n\t\t...(hooks?.pairingCodeTtlMs === undefined\n\t\t\t? {}\n\t\t\t: { pairingCodeTtlMs: hooks.pairingCodeTtlMs }),\n\t\tpublicUrl: () => publicUrl,\n\t\tasync revokeGrant(session: TabSession, grantId: string): Promise<boolean> {\n\t\t\tconst addressId = session.addressId;\n\t\t\tif (addressId === undefined) return false;\n\t\t\tconst grants = await store.listGrants(addressId, Date.now());\n\t\t\tif (!grants.some((g) => g.grantId === grantId)) return false;\n\t\t\tawait store.revoke({ grantId }, revokeOptions());\n\t\t\tlogger.info(\"oauth.revoked\", {\n\t\t\t\taddress: shortAddress(addressId),\n\t\t\t\tby: \"tab\",\n\t\t\t});\n\t\t\tgrantRemoved(addressId, grantId, \"revoked\");\n\t\t\treturn true;\n\t\t},\n\t\tasync revokeAll(session: TabSession): Promise<void> {\n\t\t\tconst addressId = session.addressId;\n\t\t\tif (addressId === undefined) return;\n\t\t\tconst grants = await store.listGrants(addressId, Date.now());\n\t\t\tawait store.revoke({ addressId }, revokeOptions());\n\t\t\tlogger.info(\"oauth.revoked_all\", {\n\t\t\t\taddress: shortAddress(addressId),\n\t\t\t\tgrants: grants.length,\n\t\t\t});\n\t\t\tfor (const g of grants) grantRemoved(addressId, g.grantId, \"revoked\");\n\t\t},\n\t\tclaimAddress(session: TabSession): TabSession | undefined {\n\t\t\tconst id = session.addressId;\n\t\t\tif (id === undefined) return undefined;\n\t\t\tconst previous = sessions.get(id);\n\t\t\tsessions.set(id, session);\n\t\t\treturn previous === session ? undefined : previous;\n\t\t},\n\t\treleased(session: TabSession): void {\n\t\t\tallSessions.delete(session);\n\t\t\tif (\n\t\t\t\tsession.addressId !== undefined &&\n\t\t\t\tsessions.get(session.addressId) === session\n\t\t\t) {\n\t\t\t\tsessions.delete(session.addressId);\n\t\t\t}\n\t\t\treleaseIp(session.ip);\n\t\t},\n\t};\n\n\tfunction releaseIp(ip: string): void {\n\t\tconst n = (perIp.get(ip) ?? 1) - 1;\n\t\tif (n <= 0) perIp.delete(ip);\n\t\telse perIp.set(ip, n);\n\t}\n\n\tfunction clientIp(req: Request, server: Server<WsData>): string {\n\t\tif (config.trustProxy === \"x-real-ip\") {\n\t\t\tconst v = req.headers.get(\"x-real-ip\")?.trim();\n\t\t\tif (v) return v;\n\t\t} else if (config.trustProxy === \"x-forwarded-for\") {\n\t\t\tconst parts = (req.headers.get(\"x-forwarded-for\") ?? \"\")\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((s) => s !== \"\");\n\t\t\tconst last = parts.at(-1);\n\t\t\tif (last !== undefined) return last;\n\t\t}\n\t\treturn server.requestIP(req)?.address ?? \"unknown\";\n\t}\n\n\tconst auth = new AuthorizationServer(\n\t\t{\n\t\t\tconfig,\n\t\t\tlogger,\n\t\t\tstore,\n\t\t\tpublicUrl: () => publicUrl,\n\t\t\tsession: (addressId) => {\n\t\t\t\tconst s = sessions.get(addressId);\n\t\t\t\treturn s?.ready === true ? s : undefined;\n\t\t\t},\n\t\t\tgrantAdded: (addressId: string, grant: GrantInfo) => {\n\t\t\t\tconst session = sessions.get(addressId);\n\t\t\t\tif (session?.ready) session.send({ type: \"grant.added\", grant });\n\t\t\t},\n\t\t\tgrantRemoved: (addressId, grantId, reason) =>\n\t\t\t\tgrantRemoved(\n\t\t\t\t\taddressId,\n\t\t\t\t\tgrantId,\n\t\t\t\t\treason as \"revoked\" | \"reuse_detected\" | \"expired\",\n\t\t\t\t),\n\t\t},\n\t\thooks,\n\t);\n\tif (hooks !== undefined) {\n\t\tlogger.warn(\"relay.test_hooks\", {\n\t\t\tmessage: \"test hooks are on: never use this relay outside tests\",\n\t\t});\n\t}\n\n\tfunction handleTab(\n\t\treq: Request,\n\t\tserver: Server<WsData>,\n\t): Response | undefined {\n\t\tconst origin = req.headers.get(\"origin\");\n\t\tconst site = siteFor(config, origin);\n\t\tif (site === undefined) {\n\t\t\tlogger.info(\"tab.refused\", { reason: \"origin\" });\n\t\t\treturn json(403, { error: \"origin_not_allowed\" });\n\t\t}\n\t\tconst offered = (req.headers.get(\"sec-websocket-protocol\") ?? \"\")\n\t\t\t.split(\",\")\n\t\t\t.map((s) => s.trim());\n\t\tif (!offered.includes(SUBPROTOCOL)) {\n\t\t\treturn json(426, {\n\t\t\t\terror: \"unsupported_protocol\",\n\t\t\t\tsupported: [SUBPROTOCOL],\n\t\t\t});\n\t\t}\n\t\tconst realIp = clientIp(req, server);\n\t\t// Counted per /64 for IPv6 (DEC-061): one subscriber owns a whole /64.\n\t\tconst ip = ipPrefixKey(realIp);\n\t\tif (allSessions.size >= config.maxSessions) {\n\t\t\tlogger.warn(\"tab.refused\", { reason: \"max_sessions\" });\n\t\t\treturn json(429, { error: \"too_many_sessions\" });\n\t\t}\n\t\tconst count = perIp.get(ip) ?? 0;\n\t\tif (count >= config.maxSessionsPerIp) {\n\t\t\tlogger.warn(\"tab.refused\", {\n\t\t\t\treason: \"max_sessions_per_ip\",\n\t\t\t\tip: truncateIp(realIp),\n\t\t\t});\n\t\t\treturn json(429, { error: \"too_many_sessions\" });\n\t\t}\n\t\tperIp.set(ip, count + 1);\n\t\tconst ok = server.upgrade(req, {\n\t\t\tdata: { ip, origin: origin ?? \"\", site },\n\t\t\theaders: { \"Sec-WebSocket-Protocol\": SUBPROTOCOL },\n\t\t});\n\t\tif (ok) return undefined;\n\t\treleaseIp(ip);\n\t\treturn json(400, { error: \"websocket_upgrade_expected\" });\n\t}\n\n\tfunction wwwAuthenticate(id: string, presented: boolean): string {\n\t\tconst metadata = `${publicUrl}/.well-known/oauth-protected-resource/a/${id}/mcp`;\n\t\tconst error = presented ? ', error=\"invalid_token\"' : \"\";\n\t\treturn `Bearer resource_metadata=\"${metadata}\", scope=\"tools\"${error}`;\n\t}\n\n\tasync function authenticate(\n\t\treq: Request,\n\t\taddressId: string,\n\t): Promise<TokenRecord | \"missing\" | \"invalid\" | \"unavailable\"> {\n\t\tconst header = req.headers.get(\"authorization\");\n\t\tif (header === null) return \"missing\";\n\t\tconst match = /^Bearer ([A-Za-z0-9._~+/-]+=*)$/i.exec(header.trim());\n\t\tconst token = match?.[1];\n\t\tif (token === undefined) return \"invalid\";\n\t\tlet record: TokenRecord | undefined;\n\t\ttry {\n\t\t\trecord = await store.get(hashToken(token));\n\t\t} catch (error) {\n\t\t\tlogger.error(\"store.error\", {\n\t\t\t\top: \"get\",\n\t\t\t\tmessage: error instanceof Error ? error.message : \"unknown\",\n\t\t\t});\n\t\t\treturn \"unavailable\";\n\t\t}\n\t\tif (\n\t\t\trecord === undefined ||\n\t\t\trecord.kind !== \"access\" ||\n\t\t\trecord.addressId !== addressId ||\n\t\t\trecord.expiresAt <= Date.now() ||\n\t\t\t!record.scopes.includes(\"tools\")\n\t\t) {\n\t\t\treturn \"invalid\";\n\t\t}\n\t\treturn record;\n\t}\n\n\tasync function readBody(\n\t\treq: Request,\n\t\tmaxBytes: number,\n\t): Promise<Body | Response> {\n\t\tconst length = Number(req.headers.get(\"content-length\") ?? \"0\");\n\t\tif (length > maxBytes) {\n\t\t\treturn rpcError(\n\t\t\t\t413,\n\t\t\t\tundefined,\n\t\t\t\t-32600,\n\t\t\t\t\"Request body too large.\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\tlet bytes: ArrayBuffer;\n\t\ttry {\n\t\t\t// Bun's idle timeout does not fire while a body is being read, so a\n\t\t\t// client that stalls mid-body would hold the socket; our own deadline\n\t\t\t// answers 408 and closes the connection.\n\t\t\tconst reading = req.arrayBuffer();\n\t\t\treading.catch(() => {}); // rejects once the socket is closed\n\t\t\tlet timer: Timer | undefined;\n\t\t\tconst deadline = new Promise<\"timeout\">((resolve) => {\n\t\t\t\ttimer = setTimeout(() => resolve(\"timeout\"), config.bodyTimeoutMs);\n\t\t\t});\n\t\t\tconst result = await Promise.race([reading, deadline]);\n\t\t\tclearTimeout(timer);\n\t\t\tif (result === \"timeout\") {\n\t\t\t\treturn rpcError(\n\t\t\t\t\t408,\n\t\t\t\t\tundefined,\n\t\t\t\t\t-32600,\n\t\t\t\t\t\"The request body did not arrive in time.\",\n\t\t\t\t\t{ ...corsHeaders, connection: \"close\" },\n\t\t\t\t);\n\t\t\t}\n\t\t\tbytes = result;\n\t\t} catch {\n\t\t\treturn rpcError(\n\t\t\t\t400,\n\t\t\t\tundefined,\n\t\t\t\t-32700,\n\t\t\t\t\"Could not read the request body.\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\tif (bytes.byteLength > maxBytes) {\n\t\t\treturn rpcError(\n\t\t\t\t413,\n\t\t\t\tundefined,\n\t\t\t\t-32600,\n\t\t\t\t\"Request body too large.\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\tlet text: string;\n\t\tlet value: unknown;\n\t\ttry {\n\t\t\ttext = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n\t\t\tvalue = JSON.parse(text);\n\t\t} catch {\n\t\t\treturn rpcError(400, undefined, -32700, \"Parse error.\", corsHeaders);\n\t\t}\n\t\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\t\treturn rpcError(\n\t\t\t\t400,\n\t\t\t\tundefined,\n\t\t\t\t-32600,\n\t\t\t\t\"The body must be one JSON-RPC message (no batches).\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\treturn { value: value as Record<string, unknown>, text };\n\t}\n\n\t/** DEC-033 / DEC-040: the protocol-version pre-check. */\n\tfunction checkVersion(\n\t\treq: Request,\n\t\tbody: Record<string, unknown>,\n\t\trpcId: RpcId | undefined,\n\t): Response | { forwardVersion: string } {\n\t\tconst header = req.headers.get(\"mcp-protocol-version\");\n\t\tif (body[\"method\"] === \"initialize\") {\n\t\t\tconst params = body[\"params\"] as Record<string, unknown> | undefined;\n\t\t\tconst requested =\n\t\t\t\ttypeof params?.[\"protocolVersion\"] === \"string\"\n\t\t\t\t\t? params[\"protocolVersion\"]\n\t\t\t\t\t: (header ?? null);\n\t\t\treturn rpcError(\n\t\t\t\t400,\n\t\t\t\trpcId,\n\t\t\t\t-32022,\n\t\t\t\t`Unsupported protocol version: ${String(requested)}. This server supports only ${MCP_PROTOCOL_VERSION}.`,\n\t\t\t\tcorsHeaders,\n\t\t\t\t{ supported: [MCP_PROTOCOL_VERSION], requested },\n\t\t\t);\n\t\t}\n\t\tif (header === MCP_PROTOCOL_VERSION) return { forwardVersion: header };\n\t\tif (\n\t\t\theader === CLAUDE_MISMATCHED_HEADER &&\n\t\t\tmetaVersion(body) === MCP_PROTOCOL_VERSION\n\t\t) {\n\t\t\t// Logged once per process; the running count is in /healthz.\n\t\t\tif (++claudeWorkarounds === 1) {\n\t\t\t\tlogger.info(\"mcp.claude_header_workaround\", {\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"accepting MCP-Protocol-Version 2025-11-25 with a 2026-07-28 body (claude-code #93290); counted in /healthz\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { forwardVersion: MCP_PROTOCOL_VERSION };\n\t\t}\n\t\tif (header === null) {\n\t\t\treturn rpcError(\n\t\t\t\t400,\n\t\t\t\trpcId,\n\t\t\t\t-32020,\n\t\t\t\t\"Missing MCP-Protocol-Version header.\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\treturn rpcError(\n\t\t\t400,\n\t\t\trpcId,\n\t\t\t-32022,\n\t\t\t`Unsupported protocol version: ${header}. This server supports only ${MCP_PROTOCOL_VERSION}.`,\n\t\t\tcorsHeaders,\n\t\t\t{ supported: [MCP_PROTOCOL_VERSION], requested: header },\n\t\t);\n\t}\n\n\tasync function handleMcp(\n\t\treq: Request,\n\t\tserver: Server<WsData>,\n\t\taddressId: string,\n\t): Promise<Response> {\n\t\tconst started = Date.now();\n\t\tconst logDone = (\n\t\t\tstatus: number,\n\t\t\tmethod: string,\n\t\t\textra: Record<string, string | number> = {},\n\t\t) =>\n\t\t\tlogger.info(\"mcp.request\", {\n\t\t\t\taddress: shortAddress(addressId),\n\t\t\t\tmethod,\n\t\t\t\tstatus,\n\t\t\t\tdurationMs: Date.now() - started,\n\t\t\t\t...extra,\n\t\t\t});\n\n\t\t// The page's own limit when it is connected; else the instance's (the\n\t\t// request then ends with 401 or 503 anyway).\n\t\tconst body = await readBody(\n\t\t\treq,\n\t\t\tsessions.get(addressId)?.limits.maxMessageBytes ?? config.maxMessageBytes,\n\t\t);\n\t\tif (body instanceof Response) {\n\t\t\tlogDone(body.status, \"?\");\n\t\t\treturn body;\n\t\t}\n\t\tconst rpcId = rpcIdOf(body.value);\n\t\tconst method = methodForLog(body.value);\n\n\t\tconst version = checkVersion(req, body.value, rpcId);\n\t\tif (version instanceof Response) {\n\t\t\tlogDone(version.status, method);\n\t\t\treturn version;\n\t\t}\n\n\t\tconst auth = await authenticate(req, addressId);\n\t\tif (auth === \"unavailable\") {\n\t\t\t// Not the token's fault: a 401 would make clients drop valid tokens.\n\t\t\tlogDone(503, method, { reason: \"store_unavailable\" });\n\t\t\treturn rpcError(\n\t\t\t\t503,\n\t\t\t\trpcId,\n\t\t\t\tRelayErrorCode.storeUnavailable,\n\t\t\t\t\"The relay cannot check tokens right now. Try again shortly.\",\n\t\t\t\t{ ...corsHeaders, \"retry-after\": \"5\" },\n\t\t\t);\n\t\t}\n\t\tif (typeof auth === \"string\") {\n\t\t\tlogDone(401, method);\n\t\t\treturn json(\n\t\t\t\t401,\n\t\t\t\t{\n\t\t\t\t\terror: \"invalid_token\",\n\t\t\t\t\terror_description:\n\t\t\t\t\t\tauth === \"missing\"\n\t\t\t\t\t\t\t? \"Authorization required.\"\n\t\t\t\t\t\t\t: \"The access token is not valid.\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t...corsHeaders,\n\t\t\t\t\t\"www-authenticate\": wwwAuthenticate(addressId, auth === \"invalid\"),\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\tconst session = sessions.get(addressId);\n\t\tif (session === undefined || !session.ready) {\n\t\t\tlogDone(503, method, { reason: \"page_not_open\" });\n\t\t\treturn rpcError(\n\t\t\t\t503,\n\t\t\t\trpcId,\n\t\t\t\tRelayErrorCode.pageNotOpen,\n\t\t\t\t'The page is not open. Open the web page that offers these tools and click \"Connect your AI app\".',\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\t\tif (session.pending.size >= session.limits.maxConcurrentRequests) {\n\t\t\tlogDone(429, method);\n\t\t\treturn rpcError(\n\t\t\t\t429,\n\t\t\t\trpcId,\n\t\t\t\tRelayErrorCode.overloaded,\n\t\t\t\t\"Too many requests at once for this page.\",\n\t\t\t\tcorsHeaders,\n\t\t\t);\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tfor (const [k, v] of req.headers) {\n\t\t\tconst key = k.toLowerCase();\n\t\t\tif (FORWARDED_HEADERS.has(key) || key.startsWith(\"mcp-param-\"))\n\t\t\t\theaders[key] = v;\n\t\t}\n\t\theaders[\"mcp-protocol-version\"] = version.forwardVersion;\n\n\t\tconst clientHostName = (() => {\n\t\t\ttry {\n\t\t\t\treturn new URL(auth.clientId).host;\n\t\t\t} catch {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t})();\n\t\t// The AI app may have gone while the body was read or the token checked:\n\t\t// then forward nothing (the abort event has already fired and would not\n\t\t// cancel the exchange, which would hold a slot until the timeout).\n\t\tif (req.signal.aborted) {\n\t\t\tlogDone(499, method, { outcome: \"client_closed\" });\n\t\t\treturn new Response(null, { status: 499 });\n\t\t}\n\t\t// Only now, for an authenticated request that is about to be forwarded,\n\t\t// switch off Bun's idle timer: our own request timer and keep-alives take\n\t\t// over (Bun research, finding 1). Body reading and every unauthenticated\n\t\t// path keep the idle timeout, so a stalled client cannot hold a socket.\n\t\tserver.timeout(req, 0);\n\t\tconst exchange = session.forward({\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: body.text,\n\t\t\trpcId,\n\t\t\tisListen: body.value[\"method\"] === \"subscriptions/listen\",\n\t\t\tgrant: {\n\t\t\t\tgrantId: auth.grantId,\n\t\t\t\tclientId: auth.clientId,\n\t\t\t\tscopes: auth.scopes,\n\t\t\t},\n\t\t\textraHeaders: corsHeaders,\n\t\t\tonDone: (e: Exchange) =>\n\t\t\t\tlogDone(e.status, method, {\n\t\t\t\t\tsession: session.sessionId,\n\t\t\t\t\tclient: clientHostName,\n\t\t\t\t\toutcome: e.outcome,\n\t\t\t\t}),\n\t\t});\n\t\treq.signal.addEventListener(\"abort\", () => exchange.clientClosed(), {\n\t\t\tonce: true,\n\t\t});\n\t\treturn exchange.response;\n\t}\n\n\tfunction preflight(req: Request): Response {\n\t\tif (!config.cors)\n\t\t\treturn new Response(null, { status: 405, headers: { allow: \"POST\" } });\n\t\tconst requested = req.headers.get(\"access-control-request-headers\") ?? \"\";\n\t\treturn new Response(null, {\n\t\t\tstatus: 204,\n\t\t\theaders: {\n\t\t\t\t...corsHeaders,\n\t\t\t\t\"access-control-allow-methods\": \"POST, OPTIONS\",\n\t\t\t\t\"access-control-allow-headers\":\n\t\t\t\t\trequested !== \"\"\n\t\t\t\t\t\t? requested\n\t\t\t\t\t\t: \"authorization, content-type, accept, mcp-protocol-version, mcp-method, mcp-name\",\n\t\t\t\t\"access-control-max-age\": \"600\",\n\t\t\t},\n\t\t});\n\t}\n\n\tconst methodNotAllowed = () =>\n\t\tnew Response(null, {\n\t\t\tstatus: 405,\n\t\t\theaders: { ...corsHeaders, allow: \"POST\" },\n\t\t});\n\n\tconst postOnly = () =>\n\t\tnew Response(null, { status: 405, headers: { allow: \"POST, OPTIONS\" } });\n\tconst largest = largestMessageBytes(config);\n\tconst ipOf = (req: Request, srv: Server<WsData>) =>\n\t\tipPrefixKey(clientIp(req, srv));\n\tconst server = Bun.serve({\n\t\tport: config.port,\n\t\thostname: config.host,\n\t\tdevelopment: false,\n\t\tmaxRequestBodySize: largest + 1024,\n\t\tidleTimeout: config.httpIdleTimeoutS,\n\t\troutes: {\n\t\t\t\"/healthz\": {\n\t\t\t\tGET: () =>\n\t\t\t\t\tjson(200, {\n\t\t\t\t\t\tstatus: \"ok\",\n\t\t\t\t\t\tversion: VERSION,\n\t\t\t\t\t\tcounters: { claudeHeaderWorkaround: claudeWorkarounds },\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\t\"/\": {\n\t\t\t\tGET: () =>\n\t\t\t\t\tnew Response(INDEX_HTML, {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"content-type\": \"text/html; charset=utf-8\",\n\t\t\t\t\t\t\t\"content-security-policy\":\n\t\t\t\t\t\t\t\t\"default-src 'none'; frame-ancestors 'none'\",\n\t\t\t\t\t\t\t\"x-content-type-options\": \"nosniff\",\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\t\"/tab\": (req, srv) => handleTab(req, srv),\n\t\t\t\"/.well-known/oauth-authorization-server\": {\n\t\t\t\tGET: () => auth.metadata(),\n\t\t\t\tOPTIONS: () => auth.preflight(\"GET\"),\n\t\t\t},\n\t\t\t\"/.well-known/oauth-protected-resource/a/:id/mcp\": {\n\t\t\t\tGET: (req) => auth.protectedResource(req.params.id),\n\t\t\t\tOPTIONS: () => auth.preflight(\"GET\"),\n\t\t\t},\n\t\t\t\"/authorize\": {\n\t\t\t\tGET: (req, srv) => auth.authorize(req, ipOf(req, srv)),\n\t\t\t\tPOST: (req, srv) => auth.authorizeSubmit(req, ipOf(req, srv)),\n\t\t\t},\n\t\t\t\"/authorize.css\": { GET: () => auth.stylesheet() },\n\t\t\t\"/token\": {\n\t\t\t\tPOST: (req, srv) => auth.token(req, ipOf(req, srv)),\n\t\t\t\tOPTIONS: () => auth.preflight(\"POST\"),\n\t\t\t\tGET: postOnly,\n\t\t\t},\n\t\t\t\"/revoke\": {\n\t\t\t\tPOST: (req, srv) => auth.revoke(req, ipOf(req, srv)),\n\t\t\t\tOPTIONS: () => auth.preflight(\"POST\"),\n\t\t\t\tGET: postOnly,\n\t\t\t},\n\t\t\t\"/a/:id/mcp\": {\n\t\t\t\tPOST: (req, srv) => {\n\t\t\t\t\tconst id = req.params.id;\n\t\t\t\t\tif (!isAddressId(id))\n\t\t\t\t\t\treturn new Response(\"Not found\", { status: 404 });\n\t\t\t\t\treturn handleMcp(req, srv, id);\n\t\t\t\t},\n\t\t\t\tOPTIONS: (req) => preflight(req),\n\t\t\t\tGET: methodNotAllowed,\n\t\t\t\tDELETE: methodNotAllowed,\n\t\t\t\tPUT: methodNotAllowed,\n\t\t\t\tPATCH: methodNotAllowed,\n\t\t\t},\n\t\t},\n\t\tfetch: () => new Response(\"Not found\", { status: 404 }),\n\t\twebsocket: {\n\t\t\tdata: {} as WsData,\n\t\t\tmaxPayloadLength: largest * 4,\n\t\t\tbackpressureLimit: config.backpressureLimitBytes,\n\t\t\tcloseOnBackpressureLimit: false,\n\t\t\tidleTimeout: 120,\n\t\t\tsendPings: true,\n\t\t\tperMessageDeflate: false,\n\t\t\topen(ws: ServerWebSocket<WsData>) {\n\t\t\t\tconst session = new TabSession(\n\t\t\t\t\tws,\n\t\t\t\t\tws.data.ip,\n\t\t\t\t\tws.data.origin,\n\t\t\t\t\tws.data.site,\n\t\t\t\t\thost,\n\t\t\t\t);\n\t\t\t\tws.data.session = session;\n\t\t\t\tallSessions.add(session);\n\t\t\t},\n\t\t\tmessage(ws: ServerWebSocket<WsData>, message: string | Buffer) {\n\t\t\t\tws.data.session?.handleFrame(\n\t\t\t\t\ttypeof message === \"string\" ? message : new Uint8Array(message),\n\t\t\t\t);\n\t\t\t},\n\t\t\tclose(ws: ServerWebSocket<WsData>, code: number) {\n\t\t\t\tws.data.session?.closed(code);\n\t\t\t},\n\t\t},\n\t});\n\n\tconst port = server.port ?? config.port;\n\tif (publicUrl === \"\") publicUrl = `http://localhost:${port}`;\n\n\tconst sweep = setInterval(() => {\n\t\tauth.sweep();\n\t\tstore\n\t\t\t.deleteExpired(Date.now())\n\t\t\t.then((n) => {\n\t\t\t\tif (n > 0) logger.debug(\"store.swept\", { deleted: n });\n\t\t\t})\n\t\t\t.catch((error: unknown) =>\n\t\t\t\tlogger.error(\"store.error\", {\n\t\t\t\t\top: \"deleteExpired\",\n\t\t\t\t\tmessage: error instanceof Error ? error.message : \"unknown\",\n\t\t\t\t}),\n\t\t\t);\n\t}, config.sweepIntervalMs);\n\n\tconst siteCount =\n\t\tconfig.allowedOrigins === \"*\"\n\t\t\t? \"*\"\n\t\t\t: config.allowedOrigins.length + config.sites.length;\n\tif (config.allowedOrigins === \"*\") {\n\t\tlogger.warn(\"relay.open_relay\", {\n\t\t\tmessage:\n\t\t\t\t\"TAB_MCP_ALLOWED_ORIGINS=* lets any website open tab sessions on this relay\",\n\t\t});\n\t} else if (siteCount === 0) {\n\t\tlogger.warn(\"relay.no_origins\", {\n\t\t\tmessage:\n\t\t\t\t\"TAB_MCP_ALLOWED_ORIGINS and TAB_MCP_SITES are empty: no page can connect\",\n\t\t});\n\t}\n\tlogger.info(\"relay.start\", {\n\t\tversion: VERSION,\n\t\turl: publicUrl,\n\t\tport,\n\t\tstore: ownsStore ? config.store : \"custom\",\n\t\torigins: siteCount,\n\t});\n\n\tlet stopping: Promise<void> | undefined;\n\treturn {\n\t\turl: publicUrl,\n\t\tport,\n\t\tconfig,\n\t\taddressFor: (secret) => `${publicUrl}/a/${addressIdFromSecret(secret)}/mcp`,\n\t\tget sessionCount() {\n\t\t\treturn allSessions.size;\n\t\t},\n\t\tstop() {\n\t\t\tstopping ??= (async () => {\n\t\t\t\tclearInterval(sweep);\n\t\t\t\tfor (const session of [...allSessions]) {\n\t\t\t\t\tsession.end(\n\t\t\t\t\t\tCloseCode.shuttingDown,\n\t\t\t\t\t\t\"relay shutting down\",\n\t\t\t\t\t\t\"shutdown\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait Bun.sleep(20); // let close frames leave\n\t\t\t\tawait server.stop(true);\n\t\t\t\tif (ownsStore) await store.close?.();\n\t\t\t\tlogger.info(\"relay.stop\", {});\n\t\t\t})();\n\t\t\treturn stopping;\n\t\t},\n\t};\n}\n"
|
|
21
21
|
],
|
|
22
|
-
"mappings": "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",
|
|
23
|
-
"debugId": "
|
|
22
|
+
"mappings": "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",
|
|
23
|
+
"debugId": "0BEEC7645167157064756E2164756E21",
|
|
24
24
|
"names": []
|
|
25
25
|
}
|