import * as Data from "effect/Data"; import * as Effect from "effect/Effect"; import { getAgentByName } from "agents"; import { loadCustomerConfig, type InstallationConfig, } from "../configuration/customer"; import type { Secret } from "../configuration/secrets"; import { decode, random, opaque, LOGIN_PURPOSE, HEALTH_PURPOSE, type BridgeClaims, } from "../shared/bridge"; import { hash, verifyAssertion } from "../server/bridge"; import { bodyBytes, bodyJson, withResponse } from "../server/http"; import { createOwnerSession, authorizeRuntimeRequest } from "./session"; import { PERSONAL_PATH } from "./runtime-path"; import type { Env } from "./personal-agent"; const CHALLENGE_COOKIE = "__Host-flarebot-login"; const cookie = (value: string, maxAge: number) => `${CHALLENGE_COOKIE}=${value}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=${maxAge}`; class BridgeDenied extends Data.TaggedError("BridgeDenied") {} type Personal = ReturnType; interface BridgeContext { request: Request; url: URL; env: Env; installation: InstallationConfig; secret: Secret; personal: Personal; } type VerifiedBridge = BridgeContext & { verification: NonNullable; }; function bridgeCall(operation: () => PromiseLike) { return Effect.tryPromise({ try: operation, catch: () => new BridgeDenied() }); } function response( body: BodyInit | null, status: number, headers: Record = {}, ) { return new Response(body, { status, headers: { "Cache-Control": "no-store", "Referrer-Policy": "no-referrer", "Content-Security-Policy": "default-src 'none'; frame-ancestors 'none'; base-uri 'none'", ...headers, }, }); } function json(value: unknown) { return response(JSON.stringify(value), 200, { "Content-Type": "application/json", }); } function challengeCookie(request: Request) { const values = (request.headers.get("Cookie") ?? "") .split(";") .map((value) => value.trim()) .filter((value) => value.startsWith(`${CHALLENGE_COOKIE}=`)); const value = values[0]?.slice(CHALLENGE_COOKIE.length + 1); return values.length === 1 && opaque(value) ? value : null; } function navigation(request: Request) { return ( request.method === "GET" && !request.headers.has("Upgrade") && (!request.headers.has("Sec-Fetch-Mode") || request.headers.get("Sec-Fetch-Mode") === "navigate") ); } function serverRequest({ request, url }: BridgeContext) { return ( request.method === "POST" && !url.search && !["Origin", "Cookie", "Sec-Fetch-Site"].some((header) => request.headers.has(header), ) ); } function bearer(request: Request) { return request.headers .get("Authorization") ?.match(/^Bearer ([A-Za-z0-9_.-]{1,4096})$/)?.[1]; } function configureDomain(context: BridgeContext) { return Effect.gen(function* () { const { personal, env, url, request } = context; const assertion = bearer(request); if ( !serverRequest(context) || url.origin !== loadCustomerConfig(env).effectiveInstallation.runtimeOrigin || !assertion ) return yield* Effect.fail(new BridgeDenied()); return json(yield* bridgeCall(() => personal.configureDomain(assertion))); }); } function domainHealth(context: BridgeContext) { return Effect.gen(function* () { const { personal, request, url } = context; if ( !serverRequest(context) || (yield* bridgeCall(() => personal.configuredDomainOrigin())) !== url.origin ) return yield* Effect.fail(new BridgeDenied()); const assertion = bearer(request); if (!assertion) return yield* Effect.fail(new BridgeDenied()); return json( yield* bridgeCall(() => personal.domainHealth(assertion, url.origin)), ); }); } function enableProvider(context: VerifiedBridge) { return Effect.gen(function* () { const assertion = bearer(context.request); if (!serverRequest(context) || !assertion) return yield* Effect.fail(new BridgeDenied()); return json( yield* bridgeCall(() => context.personal.enableOpenRouter(assertion)), ); }); } function beginLogin({ installation, personal }: VerifiedBridge) { return Effect.gen(function* () { const state = random(); const binding = random(); const verifier = random(); const challenge = yield* hash(verifier); const bindingHash = yield* hash(`${binding}.${installation.runtimeOrigin}`); yield* bridgeCall(() => personal.createLoginChallenge({ state, bindingHash, verifier, challenge, // Allow independent Worker/DO clocks within the store's ten-minute bound. expiresAt: Date.now() + 540_000, }), ); const destination = new URL( "/auth/bridge", installation.controlPlaneOrigin, ); destination.search = new URLSearchParams({ installationId: installation.installationId, state, challenge, audience: installation.runtimeOrigin, }).toString(); return response(null, 303, { Location: destination.href, "Set-Cookie": cookie(binding, 600), }); }); } function completeLogin(context: VerifiedBridge, network: typeof fetch) { return Effect.gen(function* () { const { url, request, installation, verification, personal, secret } = context; if ( [...url.searchParams.keys()].length !== 2 || ["code", "state"].some((key) => url.searchParams.getAll(key).length !== 1) ) return yield* Effect.fail(new BridgeDenied()); const code = url.searchParams.get("code"); const state = url.searchParams.get("state"); const binding = challengeCookie(request); if (!opaque(code) || !opaque(state) || !binding) return yield* Effect.fail(new BridgeDenied()); const bindingHash = yield* hash(`${binding}.${installation.runtimeOrigin}`); const challenge = yield* bridgeCall(() => personal.claimLoginChallenge(state, bindingHash), ); if (!challenge) return yield* Effect.fail(new BridgeDenied()); const result = yield* withResponse( network, new Request( new URL("/auth/bridge/exchange", installation.controlPlaneOrigin), { method: "POST", redirect: "manual", signal: request.signal, headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ code, verifier: challenge.verifier, installationId: installation.installationId, audience: installation.runtimeOrigin, state, }), }, ), {}, 10_000, new BridgeDenied(), (exchanged) => exchanged.ok ? bodyJson(exchanged, 5000, new BridgeDenied()) : Effect.fail(new BridgeDenied()), ); if ( !result || typeof result !== "object" || Object.keys(result).join(",") !== "assertion" || !("assertion" in result) || typeof result.assertion !== "string" ) return yield* Effect.fail(new BridgeDenied()); yield* verifyAssertion(result.assertion, verification, { iss: installation.controlPlaneOrigin, aud: installation.runtimeOrigin, sub: installation.ownerSubject, installationId: installation.installationId, purpose: LOGIN_PURPOSE, state, challenge: challenge.challenge, }); const reply = response(null, 303, { Location: "/", "Set-Cookie": cookie("", 0), }); reply.headers.append( "Set-Cookie", yield* createOwnerSession(secret, installation), ); return reply; }); } function bootstrapHealth(context: VerifiedBridge) { return Effect.gen(function* () { const { request, installation, verification, env, secret, personal } = context; const token = bearer(request); const release = installation.release; if ( request.headers.has("Origin") || request.headers.has("Cookie") || !token || !release ) return yield* Effect.fail(new BridgeDenied()); const untrusted: BridgeClaims = yield* Effect.try({ try: () => JSON.parse(new TextDecoder().decode(decode(token.split(".")[1]))), catch: () => new BridgeDenied(), }); if (!opaque(untrusted.state) || !opaque(untrusted.challenge)) return yield* Effect.fail(new BridgeDenied()); const claims = yield* verifyAssertion(token, verification, { iss: installation.controlPlaneOrigin, aud: installation.runtimeOrigin, sub: installation.ownerSubject, installationId: installation.installationId, purpose: HEALTH_PURPOSE, state: untrusted.state, challenge: untrusted.challenge, operationId: release.operationId, artifactDigest: release.artifactDigest, version: release.version, }); if (!env.AI || !env.BROWSER || !env.LOADER || !env.Sandbox || !env.ASSETS) return yield* Effect.fail(new BridgeDenied()); const asset = yield* bridgeCall(() => env.ASSETS.fetch( new Request( new URL("/flarebot-health.txt", installation.runtimeOrigin), ), ), ); if (!asset.ok) return yield* Effect.fail(new BridgeDenied()); const bytes = yield* bodyBytes(asset, 128, new BridgeDenied()); if (new TextDecoder().decode(bytes) !== "flarebot-assets-v1\n") return yield* Effect.fail(new BridgeDenied()); const denied = yield* authorizeRuntimeRequest( new Request(new URL(PERSONAL_PATH, installation.runtimeOrigin)), secret, installation, ); const socketDenied = yield* authorizeRuntimeRequest( new Request(new URL(PERSONAL_PATH, installation.runtimeOrigin), { headers: { Upgrade: "websocket", Origin: installation.runtimeOrigin }, }), secret, installation, ); if (denied?.status !== 401 || socketDenied?.status !== 401) return yield* Effect.fail(new BridgeDenied()); const readiness = yield* bridgeCall(() => personal.bootstrapHealth(claims)); return json({ installationId: installation.installationId, ...release, state: claims.state, challenge: claims.challenge, ...readiness, bindings: "present", assets: "ready", authentication: "required", }); }); } export function handleCustomerBridge( request: Request, env: Env, installation: InstallationConfig, secret: Secret, network: typeof fetch = fetch, ): Effect.Effect { return Effect.gen(function* () { const url = new URL(request.url); if ( ![ "/auth/login", "/auth/callback", "/auth/bootstrap-health", "/auth/provider-enabled", "/auth/domain-configuration", "/auth/domain-health", ].includes(url.pathname) ) return null; return yield* Effect.gen(function* () { if (request.url.length > 2048) return yield* Effect.fail(new BridgeDenied()); const personal = yield* bridgeCall(() => getAgentByName(env.PersonalAgent, "personal"), ); const context = { request, url, env, installation, secret, personal }; if (url.pathname === "/auth/domain-configuration") return yield* configureDomain(context); if (url.pathname === "/auth/domain-health") return yield* domainHealth(context); if (url.origin !== installation.runtimeOrigin) return yield* Effect.fail(new BridgeDenied()); if ( env.FLAREBOT_ENV === "development" && ["localhost", "127.0.0.1", "[::1]"].includes( new URL(installation.runtimeOrigin).hostname, ) && url.pathname === "/auth/login" && navigation(request) && !url.search ) return response(null, 303, { Location: "/", "Set-Cookie": yield* createOwnerSession(secret, installation), }); if (!installation.bridge) return yield* Effect.fail(new BridgeDenied()); const verified = { ...context, verification: installation.bridge }; if (url.pathname === "/auth/login" && navigation(request) && !url.search) return yield* beginLogin(verified); if (url.pathname === "/auth/callback" && navigation(request)) return yield* completeLogin(verified, network); if (request.method === "POST" && !url.search) { if (url.pathname === "/auth/provider-enabled") return yield* enableProvider(verified); if (url.pathname === "/auth/bootstrap-health") return yield* bootstrapHealth(verified); } return yield* Effect.fail(new BridgeDenied()); }).pipe( Effect.catchCause(() => Effect.succeed( response( "Owner authentication or installation verification failed.", 403, url.pathname === "/auth/callback" ? { "Set-Cookie": cookie("", 0) } : {}, ), ), ), ); }); }