@parlor/auth 0.2.0 → 0.3.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/dist/hosts.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hosts.js","sourceRoot":"","sources":["../src/hosts.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes, timingSafeEqual } from \"node:crypto\";\n\nimport {\n ActionError,\n asId,\n type DataProvider,\n defineAction,\n type GrantId,\n type HostId,\n type HostPrincipal,\n type UserId,\n} from \"@parlor/core\";\nimport { type ActionsOf, createRegistry } from \"@parlor/core/registry\";\nimport {\n type AnyPluginRoute,\n AuthFailure,\n type DeviceKeys,\n HOST_GRANTS_TAG,\n type Migration,\n type PluginHost,\n pluginRoute,\n readBoundedText,\n SHELL_ORIGINS,\n REVOCATION_HORIZON_MS,\n} from \"@parlor/server\";\nimport { sql } from \"drizzle-orm\";\nimport { calculateJwkThumbprint, compactVerify, decodeProtectedHeader } from \"jose\";\nimport { z } from \"zod\";\n\nimport { CHAT_REFUSED, chatAllows, signedIn } from \"./account.js\";\nimport { AUTH_PLUGIN, devOrigins, type ParlorAuthSettings } from \"./better-auth.js\";\nimport { type Database, jwkOf, rowsOf } from \"./database.js\";\nimport { findPendingDevice } from \"./devices.js\";\nimport { escape, failure, page } from \"./pages.js\";\nimport { RevocationSet } from \"./revocation.js\";\nimport { HOST_ASSERTION_TYP, HOST_AUDIENCE, type HostAssertion } from \"./tokens.js\";\n\nexport const HOST_CLIENT_ID = \"parlor-host\";\n\nexport const MATCHING_CODE = /^[A-Z2-9]{3}-[A-Z2-9]{3}$/;\n\nexport type HostRedirect = `http://127.0.0.1:${number}/callback` | \"urn:parlor:ipc\";\n\nexport interface HostAuthorizeRequest {\n readonly redirectUri: HostRedirect;\n readonly codeChallenge: string;\n readonly state: string;\n readonly hostName: string;\n readonly platform: string;\n readonly matchingCode: string;\n /** RFC 7638 thumbprint of the key the code exchange must be signed with. */\n readonly keyThumbprint: string;\n}\n\n/** `POST /hosts/token` */\nexport interface HostKeyExchange {\n readonly code: string;\n readonly codeVerifier: string;\n readonly publicKey: JsonWebKey;\n /** ES256 over the code with the key the authorize request named. */\n readonly proof: string;\n}\n\nexport interface AccountSummary {\n readonly userId: UserId;\n readonly name: string;\n readonly email?: string | undefined;\n}\n\n/** The device that approved the pairing; the host pins it as trusted once confirmed locally. */\nexport type ApprovingDevice = DeviceKeys;\n\nexport interface HostGrantResponse {\n readonly grant: { readonly id: GrantId; readonly hostId: HostId };\n /** The host shows it locally before it keeps the grant. */\n readonly account: AccountSummary;\n readonly approvedBy?: ApprovingDevice | undefined;\n}\n\nexport const HOST_ASSERTION_TTL_MS = 60_000;\n\n/** `authorization: ParlorHost <jws>`, DPoP style: bound to one method and URL, dead in a minute. */\nexport interface HostAssertionClaims {\n readonly aud: typeof HOST_AUDIENCE;\n readonly gid: string;\n readonly htm: \"GET\" | \"POST\";\n /** without the query */\n readonly htu: string;\n readonly iat: number;\n readonly exp: number;\n /** replay-checked in a bounded per-instance LRU over the TTL window */\n readonly jti: string;\n}\n\n/** A grant as the server stores it: only the computer's public key. */\nexport interface GrantKey {\n readonly grantId: GrantId;\n readonly userId: UserId;\n readonly hostId: HostId;\n readonly publicKey: JsonWebKey;\n readonly kid: string;\n}\n\n/** In memory after one primary-key lookup; dropped when `RevocationSet` reports the grant. */\nexport interface GrantKeys {\n get(grantId: GrantId): Promise<GrantKey | undefined>;\n}\n\nconst GRANT_KEY_TTL_MS = 5 * 60_000;\nconst GRANT_KEY_CACHE_SIZE = 10_000;\n/** A missing grant is remembered briefly; grant ids are never reused, so a miss stays one. */\nexport const GRANT_MISS_TTL_MS = 5_000;\nconst GRANT_MISS_CACHE_SIZE = 1_000;\nconst REPLAY_CACHE_SIZE = 100_000;\nconst CLOCK_SKEW_MS = 5_000;\n\nexport interface GrantKeysOptions {\n /** How long a loaded key is trusted; clamped to the revocation horizon. */\n readonly ttlMs?: number | undefined;\n readonly now?: (() => number) | undefined;\n}\n\ninterface GrantRow {\n readonly grant_id: string;\n readonly user_id: string;\n readonly host_id: string;\n readonly public_key: JsonWebKey | string;\n readonly kid: string;\n}\n\nconst verifyKeys = new WeakMap<GrantKey, Promise<CryptoKey>>();\nconst replays = new WeakMap<GrantKeys, Map<string, number>>();\n\nconst EC_P256 = { name: \"ECDSA\", namedCurve: \"P-256\" } as const;\n\nfunction verifyKeyOf(grant: GrantKey): Promise<CryptoKey> {\n let key = verifyKeys.get(grant);\n if (!key) {\n key = crypto.subtle.importKey(\"jwk\", grant.publicKey, EC_P256, false, [\"verify\"]);\n verifyKeys.set(grant, key);\n }\n return key;\n}\n\n/**\n * A grant's key after one primary-key lookup, kept for a few minutes. A grant revoked\n * meanwhile has no row, and `RevocationSet` (which outlasts the cache) refuses it until the\n * cache lets go.\n */\nexport function createGrantKeys(\n database: DataProvider,\n options: GrantKeysOptions = {},\n): GrantKeys {\n const ttlMs = Math.min(options.ttlMs ?? GRANT_KEY_TTL_MS, REVOCATION_HORIZON_MS);\n const now = options.now ?? Date.now;\n const cache = new Map<string, { readonly key: GrantKey; readonly loadedAt: number }>();\n const misses = new Map<string, number>();\n const loading = new Map<string, Promise<GrantKey | undefined>>();\n\n const load = async (grantId: GrantId): Promise<GrantKey | undefined> => {\n const rows = rowsOf<GrantRow>(\n await (database.read() as Database).execute(sql`\n select grant_id, user_id, host_id, public_key, kid from parlor_auth_hosts\n where grant_id = ${grantId}`),\n );\n const row = rows[0];\n if (!row) {\n misses.set(grantId, now());\n while (misses.size > GRANT_MISS_CACHE_SIZE) {\n misses.delete(misses.keys().next().value as string);\n }\n return undefined;\n }\n const key: GrantKey = {\n grantId: asId(\"grant\", row.grant_id),\n userId: asId(\"user\", row.user_id),\n hostId: asId(\"host\", row.host_id),\n publicKey: jwkOf(row.public_key),\n kid: row.kid,\n };\n cache.set(grantId, { key, loadedAt: now() });\n while (cache.size > GRANT_KEY_CACHE_SIZE) {\n cache.delete(cache.keys().next().value as string);\n }\n return key;\n };\n\n return {\n async get(grantId) {\n const hit = cache.get(grantId);\n if (hit && now() - hit.loadedAt < ttlMs) return hit.key;\n cache.delete(grantId);\n const missedAt = misses.get(grantId);\n if (missedAt !== undefined) {\n if (now() - missedAt < GRANT_MISS_TTL_MS) return undefined;\n misses.delete(grantId);\n }\n let pending = loading.get(grantId);\n if (!pending) {\n pending = load(grantId).finally(() => loading.delete(grantId));\n loading.set(grantId, pending);\n }\n return pending;\n },\n };\n}\n\nconst assertionClaims = z.object({\n aud: z.literal(HOST_AUDIENCE),\n gid: z.string().min(1),\n htm: z.enum([\"GET\", \"POST\"]),\n htu: z.string().min(1),\n iat: z.number().int(),\n exp: z.number().int(),\n jti: z.string().min(8).max(128),\n});\n\nconst withoutQuery = (url: string): string => {\n const parsed = new URL(url);\n parsed.search = \"\";\n parsed.hash = \"\";\n return parsed.href;\n};\n\nfunction claimJti(\n keys: GrantKeys,\n grantId: string,\n jti: string,\n now: number,\n rememberUntil: number,\n): boolean {\n let seen = replays.get(keys);\n if (!seen) replays.set(keys, (seen = new Map()));\n for (const [id, expiresAt] of seen) {\n if (expiresAt > now) break;\n seen.delete(id);\n }\n const id = `${grantId}:${jti}`;\n if (seen.has(id)) return false;\n while (seen.size >= REPLAY_CACHE_SIZE) seen.delete(seen.keys().next().value as string);\n seen.set(id, rememberUntil);\n return true;\n}\n\nfunction claimsOf(assertion: HostAssertion): { gid: string; kid: string | undefined } {\n try {\n const header = decodeProtectedHeader(assertion);\n const payload = JSON.parse(\n Buffer.from(assertion.split(\".\")[1] ?? \"\", \"base64url\").toString(\"utf8\"),\n ) as { gid?: unknown };\n if (header.typ !== HOST_ASSERTION_TYP || typeof payload.gid !== \"string\") {\n throw new Error(\"not a host assertion\");\n }\n return { gid: payload.gid, kid: header.kid };\n } catch {\n throw new AuthFailure(\"invalid\", \"The host assertion is malformed.\");\n }\n}\n\nexport async function verifyHostAssertion(\n assertion: HostAssertion,\n request: { readonly method: string; readonly url: string },\n keys: GrantKeys,\n now: number,\n): Promise<GrantKey> {\n const { gid, kid } = claimsOf(assertion);\n const grant = await keys.get(asId(\"grant\", gid));\n if (!grant || kid !== grant.kid) {\n throw new AuthFailure(\"invalid\", \"This computer is not connected.\");\n }\n let payload: unknown;\n try {\n const verified = await compactVerify(assertion, await verifyKeyOf(grant), {\n algorithms: [\"ES256\"],\n });\n payload = JSON.parse(new TextDecoder().decode(verified.payload));\n } catch {\n throw new AuthFailure(\n \"invalid\",\n \"The host assertion is not signed by this computer.\",\n );\n }\n const parsed = assertionClaims.safeParse(payload);\n if (!parsed.success)\n throw new AuthFailure(\"invalid\", \"The host assertion is malformed.\");\n const claims = parsed.data;\n if (claims.htm !== request.method) {\n throw new AuthFailure(\"invalid\", \"The host assertion is for another method.\");\n }\n let sameUrl: boolean;\n try {\n sameUrl = withoutQuery(claims.htu) === withoutQuery(request.url);\n } catch {\n sameUrl = false;\n }\n if (!sameUrl)\n throw new AuthFailure(\"invalid\", \"The host assertion is for another URL.\");\n const issuedAt = claims.iat * 1000;\n if (\n claims.exp - claims.iat > HOST_ASSERTION_TTL_MS / 1000 ||\n issuedAt - now > CLOCK_SKEW_MS\n ) {\n throw new AuthFailure(\"invalid\", \"The host assertion has an impossible lifetime.\");\n }\n if (now - issuedAt > HOST_ASSERTION_TTL_MS || claims.exp * 1000 <= now) {\n throw new AuthFailure(\"expired\", \"The host assertion expired.\");\n }\n const acceptableUntil = Math.min(claims.exp * 1000, issuedAt + HOST_ASSERTION_TTL_MS);\n if (!claimJti(keys, grant.grantId, claims.jti, now, acceptableUntil)) {\n throw new AuthFailure(\"invalid\", \"The host assertion was already used.\");\n }\n return grant;\n}\n\nexport function hostPrincipalOf(grant: GrantKey): HostPrincipal {\n return {\n kind: \"host\",\n userId: grant.userId,\n grantId: grant.grantId,\n hostId: grant.hostId,\n };\n}\n\nexport const HOSTS_TAG = HOST_GRANTS_TAG;\n\nexport const HOSTS_MIGRATION: Migration = {\n id: \"auth/0003_hosts\",\n sql: `\n create table parlor_auth_hosts (\n grant_id text primary key,\n host_id text not null unique,\n user_id text not null,\n name text not null,\n platform text not null,\n public_key jsonb not null,\n kid text not null,\n created_at timestamptz not null default now(),\n last_used_at timestamptz\n );\n create index parlor_auth_hosts_user on parlor_auth_hosts (user_id);\n\n create table parlor_auth_host_codes (\n code_hash text primary key,\n user_id text not null,\n code_challenge text not null,\n key_thumbprint text not null,\n redirect_uri text not null,\n host_name text not null,\n platform text not null,\n device_id text,\n expires_at timestamptz not null\n )`,\n};\n\nexport interface ConnectedHost {\n readonly hostId: HostId;\n readonly name: string;\n readonly platform: string;\n readonly connectedAt: string;\n readonly lastUsedAt: string | null;\n}\n\nexport interface HostGrantDeps {\n readonly host: PluginHost;\n readonly settings: ParlorAuthSettings;\n}\n\nfunction databaseOf(host: PluginHost): DataProvider {\n if (!host.database) throw new Error(\"Host grants need a database.\");\n return host.database;\n}\n\ninterface RemovedGrant {\n readonly grant_id: string;\n readonly host_id: string;\n}\n\n/**\n * Deletes the grant's key row and revokes the grant in one transaction. The row must go:\n * `RevocationSet` forgets after its horizon, and a host assertion's `iat` is always fresh.\n */\nasync function removeGrant(\n deps: HostGrantDeps,\n match: { readonly hostId: string } | { readonly grantId: string },\n userId: string,\n): Promise<RemovedGrant | undefined> {\n return databaseOf(deps.host).transaction(async (handle) => {\n const tx = handle as Database;\n const removed = rowsOf<RemovedGrant>(\n await tx.execute(\n \"hostId\" in match\n ? sql`delete from parlor_auth_hosts where host_id = ${match.hostId} and user_id = ${userId} returning grant_id, host_id`\n : sql`delete from parlor_auth_hosts where grant_id = ${match.grantId} and user_id = ${userId} returning grant_id, host_id`,\n ),\n )[0];\n if (!removed) return undefined;\n await RevocationSet.revoke(tx, { kind: \"grant\", id: removed.grant_id });\n return removed;\n });\n}\n\ninterface HostListRow {\n readonly host_id: string;\n readonly name: string;\n readonly platform: string;\n readonly created_at: string | Date;\n readonly last_used_at: string | Date | null;\n}\n\nconst isoOf = (value: string | Date): string => new Date(value).toISOString();\n\n/** `hosts` and `revokeHost`, merged into the account actions once host grants land. */\nexport function hostAccountActions(deps: HostGrantDeps) {\n return createRegistry({\n hosts: defineAction({\n description: \"List the computers connected to this account.\",\n input: z.object({}),\n reads: [HOSTS_TAG],\n run: async (_input, ctx): Promise<ConnectedHost[]> => {\n const user = signedIn(ctx);\n const rows = rowsOf<HostListRow>(\n await (databaseOf(deps.host).read() as Database).execute(sql`\n select host_id, name, platform, created_at, last_used_at from parlor_auth_hosts\n where user_id = ${user.userId} order by created_at, host_id`),\n );\n return rows.map((row) => ({\n hostId: asId(\"host\", row.host_id),\n name: row.name,\n platform: row.platform,\n connectedAt: isoOf(row.created_at),\n lastUsedAt: row.last_used_at === null ? null : isoOf(row.last_used_at),\n }));\n },\n }),\n revokeHost: defineAction({\n description:\n \"Disconnect a computer; its grant, turn tokens and stream end at once.\",\n input: z.object({ hostId: z.string().min(1) }),\n run: async ({ hostId }, ctx): Promise<{ readonly id: string }> => {\n const user = signedIn(ctx);\n const removed = await removeGrant(deps, { hostId }, user.userId);\n if (!removed) throw new ActionError(\"not_found\", `No computer ${hostId}`);\n await deps.host.announce(ctx.scope, [[HOSTS_TAG, hostId]]);\n return { id: hostId };\n },\n }),\n });\n}\n\nexport type HostAccountActions = ActionsOf<ReturnType<typeof hostAccountActions>>;\n\nconst THUMBPRINT = /^[A-Za-z0-9_-]{43}$/;\nconst isPrintable = (text: string) =>\n [...text].every((char) => {\n const code = char.codePointAt(0)!;\n return code >= 0x20 && code !== 0x7f;\n });\nconst LOOPBACK = /^http:\\/\\/127\\.0\\.0\\.1:(\\d{1,5})\\/callback$/;\nconst IPC_REDIRECT = \"urn:parlor:ipc\";\nconst CODE_TTL_MS = 10 * 60_000;\n\nfunction isHostRedirect(value: unknown): value is HostRedirect {\n if (value === IPC_REDIRECT) return true;\n if (typeof value !== \"string\") return false;\n const port = LOOPBACK.exec(value)?.[1];\n return port !== undefined && Number(port) >= 1 && Number(port) <= 65_535;\n}\n\nconst authorizeRequest = z.object({\n redirectUri: z.custom<HostRedirect>(isHostRedirect, \"Use a loopback redirect.\"),\n codeChallenge: z.string().regex(THUMBPRINT),\n state: z.string().min(1).max(256),\n hostName: z\n .string()\n .trim()\n .min(1)\n .max(64)\n .refine(isPrintable, \"Use printable characters.\"),\n platform: z\n .string()\n .trim()\n .min(1)\n .max(32)\n .refine(isPrintable, \"Use printable characters.\"),\n matchingCode: z.string().regex(MATCHING_CODE),\n keyThumbprint: z.string().regex(THUMBPRINT),\n});\n\nconst authorizeAnswer = authorizeRequest.extend({\n decision: z.enum([\"connect\", \"cancel\"]),\n});\n\nconst publicKeySchema = z.looseObject({\n kty: z.literal(\"EC\"),\n crv: z.literal(\"P-256\"),\n x: z.string().regex(THUMBPRINT),\n y: z.string().regex(THUMBPRINT),\n});\n\nconst keyExchange = z.object({\n code: z.string().min(16).max(256),\n codeVerifier: z.string().min(43).max(128),\n publicKey: publicKeySchema,\n proof: z.string().min(1).max(256),\n});\n\nconst MAX_BODY_BYTES = 16 * 1024;\n\nconst sha256 = (text: string, encoding: \"hex\" | \"base64url\") =>\n createHash(\"sha256\").update(text).digest(encoding);\n\nfunction sameText(a: string, b: string): boolean {\n const left = createHash(\"sha256\").update(a).digest();\n const right = createHash(\"sha256\").update(b).digest();\n return timingSafeEqual(left, right);\n}\n\nasync function bodyOf(\n request: Request,\n): Promise<{ readonly json: boolean; readonly fields: unknown }> {\n const text = await readBoundedText(request, MAX_BODY_BYTES);\n if (text === undefined) return { json: false, fields: undefined };\n if ((request.headers.get(\"content-type\") ?? \"\").includes(\"application/json\")) {\n try {\n return { json: true, fields: JSON.parse(text) as unknown };\n } catch {\n return { json: true, fields: undefined };\n }\n }\n return { json: false, fields: Object.fromEntries(new URLSearchParams(text)) };\n}\n\nfunction invalidGrant(): Response {\n return Response.json(\n {\n error: {\n code: \"invalid_grant\",\n message: \"The pairing code is invalid, expired or already used.\",\n },\n },\n { status: 400 },\n );\n}\n\ninterface PairingCode {\n readonly user_id: string;\n readonly code_challenge: string;\n readonly key_thumbprint: string;\n readonly host_name: string;\n readonly platform: string;\n readonly expires_at: string | Date;\n}\n\nasync function verifyProof(\n publicKey: JsonWebKey,\n code: string,\n proof: string,\n): Promise<boolean> {\n try {\n const key = await crypto.subtle.importKey(\"jwk\", publicKey, EC_P256, false, [\n \"verify\",\n ]);\n return await crypto.subtle.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n key,\n Buffer.from(proof, \"base64url\"),\n new TextEncoder().encode(code),\n );\n } catch {\n return false;\n }\n}\n\n/**\n * `GET|POST /hosts/authorize` is the framework-owned consent page and its answer, `POST\n * /hosts/token` the PKCE exchange binding the host's key, `POST /hosts/revoke` the host\n * disconnecting itself.\n */\nexport function hostRoutes(deps: HostGrantDeps): readonly AnyPluginRoute[] {\n const { host, settings } = deps;\n const appName = () =>\n process.env.PARLOR_APP_NAME ?? settings.appName ?? new URL(settings.origin).host;\n const authorizeUrl = `${host.basePath}/${AUTH_PLUGIN}/hosts/authorize`;\n const accountOf = async (userId: UserId) => host.auth?.account?.(userId);\n\n return [\n pluginRoute({\n method: \"GET\",\n path: \"/hosts/authorize\",\n access: [\"user\"],\n handle: async (request, caller) => {\n if (!(await chatAllows(host, caller))) return failure(CHAT_REFUSED, 403);\n const parsed = authorizeRequest.safeParse(\n Object.fromEntries(new URL(request.url).searchParams),\n );\n if (!parsed.success) {\n return failure(\"This connection request is incomplete.\", 400);\n }\n const pairing = parsed.data;\n const profile = await accountOf(caller.principal.userId);\n const app = appName();\n const hidden = Object.entries(pairing)\n .map(\n ([name, value]) =>\n `<input type=\"hidden\" name=\"${name}\" value=\"${escape(String(value))}\">`,\n )\n .join(\"\\n\");\n const body = `\n<h1>Connect ${escape(pairing.hostName)} to ${escape(app)}?</h1>\n<p>Signed in as <strong>${escape(profile?.email ?? profile?.name ?? \"your account\")}</strong>.</p>\n<p>The coding agents on <strong>${escape(pairing.hostName)}</strong> (${escape(pairing.platform)}) will take your prompts from ${escape(app)} and run on that computer. Continue only if you just ran <code>connect</code> there.</p>\n<form method=\"post\" action=\"${escape(authorizeUrl)}\">\n${hidden}\n<button type=\"submit\" name=\"decision\" value=\"cancel\">Cancel</button>\n<button type=\"submit\" name=\"decision\" value=\"connect\">Connect</button>\n</form>`;\n const target =\n pairing.redirectUri === IPC_REDIRECT\n ? []\n : [new URL(pairing.redirectUri).origin];\n return page(\"Connect a computer\", body, [\"'self'\", ...target]);\n },\n }),\n pluginRoute({\n method: \"POST\",\n path: \"/hosts/authorize\",\n access: [\"user\"],\n handle: async (request, caller) => {\n const { json, fields } = await bodyOf(request);\n const refuse = (status: number, code: string, message: string) =>\n json\n ? Response.json({ error: { code, message } }, { status })\n : failure(message, status);\n const origin = request.headers.get(\"origin\");\n if (\n origin !== settings.origin &&\n !(origin && [...SHELL_ORIGINS, ...devOrigins()].includes(origin))\n ) {\n return refuse(\n 403,\n \"forbidden\",\n \"This answer did not come from the consent page.\",\n );\n }\n if (!(await chatAllows(host, caller))) {\n return refuse(403, \"forbidden\", CHAT_REFUSED);\n }\n const parsed = authorizeAnswer.safeParse(fields);\n if (!parsed.success) {\n return refuse(400, \"invalid_input\", \"This connection request is incomplete.\");\n }\n const { decision, ...pairing } = parsed.data;\n const target =\n pairing.redirectUri === IPC_REDIRECT ? undefined : new URL(pairing.redirectUri);\n if (decision === \"cancel\") {\n if (!target)\n return Response.json({ error: \"access_denied\", state: pairing.state });\n target.searchParams.set(\"error\", \"access_denied\");\n target.searchParams.set(\"state\", pairing.state);\n return new Response(null, { status: 303, headers: { location: target.href } });\n }\n const code = randomBytes(32).toString(\"base64url\");\n await databaseOf(host).transaction(async (handle) => {\n const tx = handle as Database;\n await tx.execute(\n sql`delete from parlor_auth_host_codes where expires_at < ${new Date().toISOString()}`,\n );\n await tx.execute(sql`\n insert into parlor_auth_host_codes\n (code_hash, user_id, code_challenge, key_thumbprint, redirect_uri, host_name, platform, expires_at)\n values (${sha256(code, \"hex\")}, ${caller.principal.userId}, ${pairing.codeChallenge},\n ${pairing.keyThumbprint}, ${pairing.redirectUri}, ${pairing.hostName}, ${pairing.platform},\n ${new Date(Date.now() + CODE_TTL_MS).toISOString()})`);\n });\n if (!target) return Response.json({ code, state: pairing.state });\n target.searchParams.set(\"code\", code);\n target.searchParams.set(\"state\", pairing.state);\n return new Response(null, { status: 303, headers: { location: target.href } });\n },\n }),\n {\n method: \"POST\",\n path: \"/hosts/token\",\n access: \"public\",\n handle: async (request) => {\n const { fields } = await bodyOf(request);\n const exchange = keyExchange.safeParse(fields);\n if (!exchange.success || \"d\" in exchange.data.publicKey) return invalidGrant();\n const { code, codeVerifier, proof } = exchange.data;\n const { kty, crv, x, y } = exchange.data.publicKey;\n const publicKey: JsonWebKey = { kty, crv, x, y };\n const database = databaseOf(host);\n const stored = await database.transaction(\n async (handle) =>\n rowsOf<PairingCode>(\n await (handle as Database).execute(sql`\n delete from parlor_auth_host_codes where code_hash = ${sha256(code, \"hex\")}\n returning user_id, code_challenge, key_thumbprint, host_name, platform, expires_at`),\n )[0],\n );\n if (\n !stored ||\n new Date(stored.expires_at).getTime() <= Date.now() ||\n !sameText(sha256(codeVerifier, \"base64url\"), stored.code_challenge) ||\n !sameText(\n await calculateJwkThumbprint(publicKey, \"sha256\"),\n stored.key_thumbprint,\n ) ||\n !(await verifyProof(publicKey, code, proof))\n ) {\n return invalidGrant();\n }\n const grantId = asId(\"grant\", `host:${crypto.randomUUID()}`);\n const hostId = asId(\"host\", crypto.randomUUID());\n const userId = asId(\"user\", stored.user_id);\n await database.transaction(async (handle) => {\n await (handle as Database).execute(sql`\n insert into parlor_auth_hosts (grant_id, host_id, user_id, name, platform, public_key, kid)\n values (${grantId}, ${hostId}, ${userId}, ${stored.host_name}, ${stored.platform},\n ${JSON.stringify(publicKey)}::jsonb, ${stored.key_thumbprint})`);\n });\n await host.announce(userId, [[HOSTS_TAG, hostId]]);\n const profile = await accountOf(userId);\n const response: HostGrantResponse = {\n grant: { id: grantId, hostId },\n account: { userId, name: profile?.name ?? \"\", email: profile?.email },\n };\n return Response.json(response);\n },\n },\n pluginRoute({\n method: \"POST\",\n path: \"/hosts/devices/link\",\n access: [\"host\"],\n handle: async (request, caller) => {\n if (!(await chatAllows(host, caller))) {\n return Response.json(\n { error: { code: \"forbidden\", message: CHAT_REFUSED } },\n { status: 403 },\n );\n }\n const { fields } = await bodyOf(request);\n const code =\n z.object({ code: z.string().max(32) }).safeParse(fields).data?.code ?? \"\";\n const found = await findPendingDevice(databaseOf(host), caller.principal.userId, {\n code,\n });\n if (!found) {\n return Response.json(\n {\n error: {\n code: \"not_found\",\n message:\n \"No device of this account shows that code. Check it, or show a new code on the device.\",\n },\n },\n { status: 404 },\n );\n }\n return Response.json(found);\n },\n }),\n pluginRoute({\n method: \"POST\",\n path: \"/hosts/revoke\",\n access: [\"host\"],\n handle: async (_request, caller) => {\n const { userId, grantId } = caller.principal;\n const removed = await removeGrant(deps, { grantId }, userId);\n if (removed) await host.announce(caller.scope, [[HOSTS_TAG, removed.host_id]]);\n return Response.json({ id: grantId });\n },\n }),\n ];\n}\n"]}
1
+ {"version":3,"file":"hosts.js","sourceRoot":"","sources":["../src/hosts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,EACL,WAAW,EACX,IAAI,EAEJ,YAAY,GAKb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAkB,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAEL,WAAW,EAEX,eAAe,EAGf,WAAW,EACX,eAAe,EACf,aAAa,EACb,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,MAAM,CAAC;AACpF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,UAAU,EAA2B,MAAM,kBAAkB,CAAC;AACpF,OAAO,EAAiB,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAsB,MAAM,aAAa,CAAC;AAEpF,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC;AAE5C,MAAM,CAAC,MAAM,aAAa,GAAG,2BAA2B,CAAC;AA4CzD,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC;AA6B5C,MAAM,gBAAgB,GAAG,CAAC,GAAG,MAAM,CAAC;AACpC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AACpC,8FAA8F;AAC9F,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AACvC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AACpC,MAAM,iBAAiB,GAAG,OAAO,CAAC;AAClC,MAAM,aAAa,GAAG,KAAK,CAAC;AAgB5B,MAAM,UAAU,GAAG,IAAI,OAAO,EAAgC,CAAC;AAC/D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAkC,CAAC;AAE9D,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAW,CAAC;AAEhE,SAAS,WAAW,CAAC,KAAe;IAClC,IAAI,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QAClF,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAsB,EACtB,OAAO,GAAqB,EAAE;IAE9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,gBAAgB,EAAE,qBAAqB,CAAC,CAAC;IACjF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiE,CAAC;IACvF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAyC,CAAC;IAEjE,MAAM,IAAI,GAAG,KAAK,EAAE,OAAgB,EAAiC,EAAE;QACrE,MAAM,IAAI,GAAG,MAAM,CACjB,MAAO,QAAQ,CAAC,IAAI,EAAe,CAAC,OAAO,CAAC,GAAG,CAAA;;2BAE1B,OAAO,EAAE,CAAC,CAChC,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;YAC3B,OAAO,MAAM,CAAC,IAAI,GAAG,qBAAqB,EAAE,CAAC;gBAC3C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAe,CAAC,CAAC;YACtD,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,GAAG,GAAa;YACpB,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC;YACpC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC;YACjC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC;YACjC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;YAChC,GAAG,EAAE,GAAG,CAAC,GAAG;SACb,CAAC;QACF,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAC7C,OAAO,KAAK,CAAC,IAAI,GAAG,oBAAoB,EAAE,CAAC;YACzC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAe,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,OAAO;YACf,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC/B,IAAI,GAAG,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,QAAQ,GAAG,KAAK;gBAAE,OAAO,GAAG,CAAC,GAAG,CAAC;YACxD,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACtB,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,IAAI,GAAG,EAAE,GAAG,QAAQ,GAAG,iBAAiB;oBAAE,OAAO,SAAS,CAAC;gBAC3D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACzB,CAAC;YACD,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;gBAC/D,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAChC,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAC7B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC5B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;CAChC,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE;IAC3C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;IACjB,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC,CAAC;AAEF,SAAS,QAAQ,CACf,IAAe,EACf,OAAe,EACf,GAAW,EACX,GAAW,EACX,aAAqB;IAErB,IAAI,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;IACjD,KAAK,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC;QACnC,IAAI,SAAS,GAAG,GAAG;YAAE,MAAM;QAC3B,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,EAAE,GAAG,GAAG,OAAO,IAAI,GAAG,EAAE,CAAC;IAC/B,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/B,OAAO,IAAI,CAAC,IAAI,IAAI,iBAAiB;QAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAe,CAAC,CAAC;IACvF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,SAAwB;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACxB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CACpD,CAAC;QACvB,IAAI,MAAM,CAAC,GAAG,KAAK,kBAAkB,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YACzE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CAAC,SAAS,EAAE,kCAAkC,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAwB,EACxB,OAA0D,EAC1D,IAAe,EACf,GAAW;IAEX,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACjD,IAAI,CAAC,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,IAAI,WAAW,CAAC,SAAS,EAAE,iCAAiC,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,MAAM,WAAW,CAAC,KAAK,CAAC,EAAE;YACxE,UAAU,EAAE,CAAC,OAAO,CAAC;SACtB,CAAC,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CACnB,SAAS,EACT,oDAAoD,CACrD,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAClD,IAAI,CAAC,MAAM,CAAC,OAAO;QACjB,MAAM,IAAI,WAAW,CAAC,SAAS,EAAE,kCAAkC,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC;IAC3B,IAAI,MAAM,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,WAAW,CAAC,SAAS,EAAE,2CAA2C,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,KAAK,CAAC;IAClB,CAAC;IACD,IAAI,CAAC,OAAO;QACV,MAAM,IAAI,WAAW,CAAC,SAAS,EAAE,wCAAwC,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC;IACnC,IACE,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,GAAG,qBAAqB,GAAG,IAAI;QACtD,QAAQ,GAAG,GAAG,GAAG,aAAa,EAC9B,CAAC;QACD,MAAM,IAAI,WAAW,CAAC,SAAS,EAAE,gDAAgD,CAAC,CAAC;IACrF,CAAC;IACD,IAAI,GAAG,GAAG,QAAQ,GAAG,qBAAqB,IAAI,MAAM,CAAC,GAAG,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC;QACvE,MAAM,IAAI,WAAW,CAAC,SAAS,EAAE,6BAA6B,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,EAAE,QAAQ,GAAG,qBAAqB,CAAC,CAAC;IACtF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,eAAe,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,WAAW,CAAC,SAAS,EAAE,sCAAsC,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAe;IAC7C,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,eAAe,CAAC;AAEzC,MAAM,CAAC,MAAM,eAAe,GAAc;IACxC,EAAE,EAAE,iBAAiB;IACrB,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;;;MAwBD;CACL,CAAC;AAeF,SAAS,UAAU,CAAC,IAAgB;IAClC,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC,QAAQ,CAAC;AACvB,CAAC;AAOD;;;GAGG;AACH,KAAK,UAAU,WAAW,CACxB,IAAmB,EACnB,KAAiE,EACjE,MAAc;IAEd,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;QACxD,MAAM,EAAE,GAAG,MAAkB,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,CACpB,MAAM,EAAE,CAAC,OAAO,CACd,QAAQ,IAAI,KAAK;YACf,CAAC,CAAC,GAAG,CAAA,iDAAiD,KAAK,CAAC,MAAM,kBAAkB,MAAM,8BAA8B;YACxH,CAAC,CAAC,GAAG,CAAA,kDAAkD,KAAK,CAAC,OAAO,kBAAkB,MAAM,8BAA8B,CAC7H,CACF,CAAC,CAAC,CAAC,CAAC;QACL,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAC/B,MAAM,aAAa,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxE,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;AACL,CAAC;AAUD,MAAM,KAAK,GAAG,CAAC,KAAoB,EAAU,EAAE,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;AAE9E,uFAAuF;AACvF,MAAM,UAAU,kBAAkB,CAAC,IAAmB;IACpD,OAAO,cAAc,CAAC;QACpB,KAAK,EAAE,YAAY,CAAC;YAClB,WAAW,EAAE,+CAA+C;YAC5D,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;YACnB,KAAK,EAAE,CAAC,SAAS,CAAC;YAClB,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAA4B,EAAE;gBACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC3B,MAAM,IAAI,GAAG,MAAM,CACjB,MAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAe,CAAC,OAAO,CAAC,GAAG,CAAA;;8BAExC,IAAI,CAAC,MAAM,+BAA+B,CAAC,CAChE,CAAC;gBACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;oBACxB,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC;oBACjC,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;oBACtB,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;oBAClC,UAAU,EAAE,GAAG,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC;iBACvE,CAAC,CAAC,CAAC;YACN,CAAC;SACF,CAAC;QACF,UAAU,EAAE,YAAY,CAAC;YACvB,WAAW,EACT,uEAAuE;YACzE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9C,GAAG,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,EAAoC,EAAE;gBAC/D,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC3B,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;gBACjE,IAAI,CAAC,OAAO;oBAAE,MAAM,IAAI,WAAW,CAAC,WAAW,EAAE,eAAe,MAAM,EAAE,CAAC,CAAC;gBAC1E,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;gBAC3D,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;YACxB,CAAC;SACF,CAAC;KACH,CAAC,CAAC;AACL,CAAC;AAID,MAAM,UAAU,GAAG,qBAAqB,CAAC;AACzC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAE,CACnC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;IACvB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC;IAClC,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC;AACvC,CAAC,CAAC,CAAC;AACL,MAAM,QAAQ,GAAG,6CAA6C,CAAC;AAC/D,MAAM,YAAY,GAAG,gBAAgB,CAAC;AACtC,MAAM,WAAW,GAAG,EAAE,GAAG,MAAM,CAAC;AAEhC,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,KAAK,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;AAC3E,CAAC;AAED,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAe,cAAc,EAAE,0BAA0B,CAAC;IAC/E,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;IAC3C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACjC,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,MAAM,CAAC,WAAW,EAAE,2BAA2B,CAAC;IACnD,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,MAAM,CAAC,WAAW,EAAE,2BAA2B,CAAC;IACnD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC;IAC7C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;IAC3C,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE;CAC5C,CAAC,CAAC;AAEH,MAAM,eAAe,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAC9C,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACvC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC;AAEH,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC;IACpC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACpB,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACvB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;IAC/B,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;CAChC,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACjC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACzC,SAAS,EAAE,eAAe;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;CAClC,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,CAAC;AAEjC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,QAA6B,EAAE,EAAE,CAC7D,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAErD,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS;IACpC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACrD,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACtD,OAAO,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,KAAK,UAAU,MAAM,CACnB,OAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAC5D,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAClE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7E,IAAI,CAAC;YACH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,EAAE,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;AAChF,CAAC;AAED,SAAS,YAAY;IACnB,OAAO,QAAQ,CAAC,IAAI,CAClB;QACE,KAAK,EAAE;YACL,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,uDAAuD;SACjE;KACF,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;AACJ,CAAC;AAWD,KAAK,UAAU,WAAW,CACxB,SAAqB,EACrB,IAAY,EACZ,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;YAC1E,QAAQ;SACT,CAAC,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAC/B,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAClC,GAAG,EACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,EAC/B,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAC/B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,6FAA6F;AAC7F,MAAM,gBAAgB,GAAG,4BAA4B,CAAC;AAEtD,MAAM,YAAY,GAAG,+DAA+D,IAAI,CAAC,SAAS,CAAC,qBAAqB,CAAC,+BAA+B,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,4DAA4D,CAAC;AAErP;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAAmB;IAC5C,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,OAAO,GAAG,GAAG,EAAE,CACnB,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,QAAQ,CAAC,OAAO,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;IACnF,MAAM,YAAY,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,WAAW,kBAAkB,CAAC;IACvE,MAAM,YAAY,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,WAAW,kBAAkB,CAAC;IACvE,MAAM,SAAS,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IAEzE,OAAO;QACL,WAAW,CAAC;YACV,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,CAAC,MAAM,CAAC;YAChB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;gBAChC,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;oBAAE,OAAO,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;gBACzE,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CACvC,MAAM,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CACtD,CAAC;gBACF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBACpB,OAAO,OAAO,CAAC,wCAAwC,EAAE,GAAG,CAAC,CAAC;gBAChE,CAAC;gBACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;gBAC5B,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBACzD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;gBACtB,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;qBACnC,GAAG,CACF,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAChB,8BAA8B,IAAI,YAAY,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAC1E;qBACA,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,MAAM,IAAI,GAAG;cACP,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC;0BAC9B,MAAM,CAAC,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,IAAI,IAAI,cAAc,CAAC;kCACjD,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,iCAAiC,MAAM,CAAC,GAAG,CAAC;8BAC9G,MAAM,CAAC,YAAY,CAAC;EAChD,MAAM;EAEN,OAAO,CAAC,UAAU,KAAK,SAAS;oBAC9B,CAAC,CAAC,kJAAkJ,MAAM,CAAC,GAAG,CAAC,4FAA4F;oBAC3P,CAAC,CAAC,EACN;;;QAGQ,CAAC;gBACD,MAAM,MAAM,GACV,OAAO,CAAC,WAAW,KAAK,YAAY;oBAClC,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;gBAC5C,OAAO,IAAI,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;YACjE,CAAC;SACF,CAAC;QACF,WAAW,CAAC;YACV,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,CAAC,MAAM,CAAC;YAChB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;gBAChC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC/C,MAAM,MAAM,GAAG,CAAC,MAAc,EAAE,IAAY,EAAE,OAAe,EAAE,EAAE,CAC/D,IAAI;oBACF,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;oBACzD,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC7C,IACE,MAAM,KAAK,QAAQ,CAAC,MAAM;oBAC1B,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,aAAa,EAAE,GAAG,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EACjE,CAAC;oBACD,OAAO,MAAM,CACX,GAAG,EACH,WAAW,EACX,iDAAiD,CAClD,CAAC;gBACJ,CAAC;gBACD,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;oBACtC,OAAO,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;gBAChD,CAAC;gBACD,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBACjD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBACpB,OAAO,MAAM,CAAC,GAAG,EAAE,eAAe,EAAE,wCAAwC,CAAC,CAAC;gBAChF,CAAC;gBACD,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;gBAC5D,MAAM,MAAM,GACV,OAAO,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;gBAClF,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBAC1B,IAAI,CAAC,MAAM;wBACT,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;oBACzE,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;oBAClD,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;oBAChD,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACjF,CAAC;gBACD,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBACnD,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;oBAClD,MAAM,EAAE,GAAG,MAAkB,CAAC;oBAC9B,MAAM,EAAE,CAAC,OAAO,CACd,GAAG,CAAA,yDAAyD,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CACvF,CAAC;oBACF,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;;sBAGR,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,OAAO,CAAC,aAAa;gBAC/E,OAAO,CAAC,aAAa,KAAK,OAAO,CAAC,WAAW,KAAK,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ;gBACvF,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;gBAC7D,CAAC,CAAC,CAAC;gBACH,MAAM,UAAU,GACd,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;gBACxE,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,OAAO,QAAQ,CAAC,IAAI,CAAC;wBACnB,IAAI;wBACJ,KAAK,EAAE,OAAO,CAAC,KAAK;wBACpB,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;qBACpD,CAAC,CAAC;gBACL,CAAC;gBACD,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACtC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;gBAChD,IAAI,UAAU,KAAK,SAAS;oBAC1B,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBACnE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACjF,CAAC;SACF,CAAC;QACF;YACE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBACxB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;gBACzC,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC/C,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS;oBAAE,OAAO,YAAY,EAAE,CAAC;gBAC/E,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC;gBACpD,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;gBACnD,MAAM,SAAS,GAAe,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;gBACjD,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;gBAClC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,WAAW,CACvC,KAAK,EAAE,MAAM,EAAE,EAAE,CACf,MAAM,CACJ,MAAO,MAAmB,CAAC,OAAO,CAAC,GAAG,CAAA;qEACiB,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;iGACS,CAAC,CACrF,CAAC,CAAC,CAAC,CACP,CAAC;gBACF,IACE,CAAC,MAAM;oBACP,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE;oBACnD,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;oBACnE,CAAC,QAAQ,CACP,MAAM,sBAAsB,CAAC,SAAS,EAAE,QAAQ,CAAC,EACjD,MAAM,CAAC,cAAc,CACtB;oBACD,CAAC,CAAC,MAAM,WAAW,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,EAC5C,CAAC;oBACD,OAAO,YAAY,EAAE,CAAC;gBACxB,CAAC;gBACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;gBAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;gBACjD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC5C,MAAM,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;oBAC1C,MAAO,MAAmB,CAAC,OAAO,CAAC,GAAG,CAAA;;sBAE1B,OAAO,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,CAAC,SAAS,KAAK,MAAM,CAAC,QAAQ;gBAC5E,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,YAAY,MAAM,CAAC,cAAc,GAAG,CAAC,CAAC;gBACvE,CAAC,CAAC,CAAC;gBACH,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;gBACnD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;gBACxC,MAAM,QAAQ,GAAsB;oBAClC,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;oBAC9B,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;oBACrE,OAAO,EAAE,YAAY;iBACtB,CAAC;gBACF,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACjC,CAAC;SACF;QACD;YACE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBACxB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAClE,MAAM,IAAI,GACR,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;oBACnC,CAAC,CAAC,oBAAoB,GAAG;;;8BAGP,GAAG;uEACsC,MAAM,CAAC,KAAK,CAAC;;+BAErD;oBACnB,CAAC,CAAC,oBAAoB,GAAG;0EACqC,GAAG,+BAA+B,CAAC;gBACrG,OAAO,IAAI,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC,CAAC;YACpE,CAAC;SACF;QACD,WAAW,CAAC;YACV,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,qBAAqB;YAC3B,MAAM,EAAE,CAAC,MAAM,CAAC;YAChB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;gBAChC,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;oBACtC,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,EACvD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;gBACJ,CAAC;gBACD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;gBACzC,MAAM,IAAI,GACR,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;gBAC5E,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;oBAC/E,IAAI;iBACL,CAAC,CAAC;gBACH,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,OAAO,QAAQ,CAAC,IAAI,CAClB;wBACE,KAAK,EAAE;4BACL,IAAI,EAAE,WAAW;4BACjB,OAAO,EACL,wFAAwF;yBAC3F;qBACF,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;gBACJ,CAAC;gBACD,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;SACF,CAAC;QACF,WAAW,CAAC;YACV,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,CAAC,MAAM,CAAC;YAChB,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE;gBACjC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;gBAC7C,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;gBAC7D,IAAI,OAAO;oBAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC/E,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;YACxC,CAAC;SACF,CAAC;KACH,CAAC;AACJ,CAAC","sourcesContent":["import { createHash, randomBytes, timingSafeEqual } from \"node:crypto\";\n\nimport {\n ActionError,\n asId,\n type DataProvider,\n defineAction,\n type GrantId,\n type HostId,\n type HostPrincipal,\n type UserId,\n} from \"@parlor/core\";\nimport { type ActionsOf, createRegistry } from \"@parlor/core/registry\";\nimport {\n type AnyPluginRoute,\n AuthFailure,\n type DeviceKeys,\n HOST_GRANTS_TAG,\n type Migration,\n type PluginHost,\n pluginRoute,\n readBoundedText,\n SHELL_ORIGINS,\n REVOCATION_HORIZON_MS,\n} from \"@parlor/server\";\nimport { sql } from \"drizzle-orm\";\nimport { calculateJwkThumbprint, compactVerify, decodeProtectedHeader } from \"jose\";\nimport { z } from \"zod\";\n\nimport { CHAT_REFUSED, chatAllows, signedIn } from \"./account.js\";\nimport { AUTH_PLUGIN, devOrigins, type ParlorAuthSettings } from \"./better-auth.js\";\nimport { type Database, jwkOf, rowsOf } from \"./database.js\";\nimport { findPendingDevice } from \"./devices.js\";\nimport { escape, failure, page } from \"./pages.js\";\nimport { RevocationSet } from \"./revocation.js\";\nimport { HOST_PAIRING_FRAGMENT, HOST_PAIRING_KEY } from \"./statements.js\";\nimport { HOST_ASSERTION_TYP, HOST_AUDIENCE, type HostAssertion } from \"./tokens.js\";\n\nexport const HOST_CLIENT_ID = \"parlor-host\";\n\nexport const MATCHING_CODE = /^[A-Z2-9]{3}-[A-Z2-9]{3}$/;\n\nexport type HostRedirect = `http://127.0.0.1:${number}/callback` | \"urn:parlor:ipc\";\n\nexport interface HostAuthorizeRequest {\n readonly redirectUri: HostRedirect;\n readonly codeChallenge: string;\n readonly state: string;\n readonly hostName: string;\n readonly platform: string;\n readonly matchingCode: string;\n /** RFC 7638 thumbprint of the key the code exchange must be signed with. */\n readonly keyThumbprint: string;\n /** The host can also hand the app to the coding agents on the computer, outside the sidebar. */\n readonly agentTools?: \"offered\" | undefined;\n}\n\n/** `POST /hosts/token` */\nexport interface HostKeyExchange {\n readonly code: string;\n readonly codeVerifier: string;\n readonly publicKey: JsonWebKey;\n /** ES256 over the code with the key the authorize request named. */\n readonly proof: string;\n}\n\nexport interface AccountSummary {\n readonly userId: UserId;\n readonly name: string;\n readonly email?: string | undefined;\n}\n\n/** The device that approved the pairing; the host pins it as trusted once confirmed locally. */\nexport type ApprovingDevice = DeviceKeys;\n\nexport interface HostGrantResponse {\n readonly grant: { readonly id: GrantId; readonly hostId: HostId };\n /** The host shows it locally before it keeps the grant. */\n readonly account: AccountSummary;\n readonly approvedBy?: ApprovingDevice | undefined;\n /** The app's page, on its origin, that the host sends the approving browser to with the pairing secret. */\n readonly landing?: string | undefined;\n}\n\nexport const HOST_ASSERTION_TTL_MS = 60_000;\n\n/** `authorization: ParlorHost <jws>`, DPoP style: bound to one method and URL, dead in a minute. */\nexport interface HostAssertionClaims {\n readonly aud: typeof HOST_AUDIENCE;\n readonly gid: string;\n readonly htm: \"GET\" | \"POST\";\n /** without the query */\n readonly htu: string;\n readonly iat: number;\n readonly exp: number;\n /** replay-checked in a bounded per-instance LRU over the TTL window */\n readonly jti: string;\n}\n\n/** A grant as the server stores it: only the computer's public key. */\nexport interface GrantKey {\n readonly grantId: GrantId;\n readonly userId: UserId;\n readonly hostId: HostId;\n readonly publicKey: JsonWebKey;\n readonly kid: string;\n}\n\n/** In memory after one primary-key lookup; dropped when `RevocationSet` reports the grant. */\nexport interface GrantKeys {\n get(grantId: GrantId): Promise<GrantKey | undefined>;\n}\n\nconst GRANT_KEY_TTL_MS = 5 * 60_000;\nconst GRANT_KEY_CACHE_SIZE = 10_000;\n/** A missing grant is remembered briefly; grant ids are never reused, so a miss stays one. */\nexport const GRANT_MISS_TTL_MS = 5_000;\nconst GRANT_MISS_CACHE_SIZE = 1_000;\nconst REPLAY_CACHE_SIZE = 100_000;\nconst CLOCK_SKEW_MS = 5_000;\n\nexport interface GrantKeysOptions {\n /** How long a loaded key is trusted; clamped to the revocation horizon. */\n readonly ttlMs?: number | undefined;\n readonly now?: (() => number) | undefined;\n}\n\ninterface GrantRow {\n readonly grant_id: string;\n readonly user_id: string;\n readonly host_id: string;\n readonly public_key: JsonWebKey | string;\n readonly kid: string;\n}\n\nconst verifyKeys = new WeakMap<GrantKey, Promise<CryptoKey>>();\nconst replays = new WeakMap<GrantKeys, Map<string, number>>();\n\nconst EC_P256 = { name: \"ECDSA\", namedCurve: \"P-256\" } as const;\n\nfunction verifyKeyOf(grant: GrantKey): Promise<CryptoKey> {\n let key = verifyKeys.get(grant);\n if (!key) {\n key = crypto.subtle.importKey(\"jwk\", grant.publicKey, EC_P256, false, [\"verify\"]);\n verifyKeys.set(grant, key);\n }\n return key;\n}\n\n/**\n * A grant's key after one primary-key lookup, kept for a few minutes. A grant revoked\n * meanwhile has no row, and `RevocationSet` (which outlasts the cache) refuses it until the\n * cache lets go.\n */\nexport function createGrantKeys(\n database: DataProvider,\n options: GrantKeysOptions = {},\n): GrantKeys {\n const ttlMs = Math.min(options.ttlMs ?? GRANT_KEY_TTL_MS, REVOCATION_HORIZON_MS);\n const now = options.now ?? Date.now;\n const cache = new Map<string, { readonly key: GrantKey; readonly loadedAt: number }>();\n const misses = new Map<string, number>();\n const loading = new Map<string, Promise<GrantKey | undefined>>();\n\n const load = async (grantId: GrantId): Promise<GrantKey | undefined> => {\n const rows = rowsOf<GrantRow>(\n await (database.read() as Database).execute(sql`\n select grant_id, user_id, host_id, public_key, kid from parlor_auth_hosts\n where grant_id = ${grantId}`),\n );\n const row = rows[0];\n if (!row) {\n misses.set(grantId, now());\n while (misses.size > GRANT_MISS_CACHE_SIZE) {\n misses.delete(misses.keys().next().value as string);\n }\n return undefined;\n }\n const key: GrantKey = {\n grantId: asId(\"grant\", row.grant_id),\n userId: asId(\"user\", row.user_id),\n hostId: asId(\"host\", row.host_id),\n publicKey: jwkOf(row.public_key),\n kid: row.kid,\n };\n cache.set(grantId, { key, loadedAt: now() });\n while (cache.size > GRANT_KEY_CACHE_SIZE) {\n cache.delete(cache.keys().next().value as string);\n }\n return key;\n };\n\n return {\n async get(grantId) {\n const hit = cache.get(grantId);\n if (hit && now() - hit.loadedAt < ttlMs) return hit.key;\n cache.delete(grantId);\n const missedAt = misses.get(grantId);\n if (missedAt !== undefined) {\n if (now() - missedAt < GRANT_MISS_TTL_MS) return undefined;\n misses.delete(grantId);\n }\n let pending = loading.get(grantId);\n if (!pending) {\n pending = load(grantId).finally(() => loading.delete(grantId));\n loading.set(grantId, pending);\n }\n return pending;\n },\n };\n}\n\nconst assertionClaims = z.object({\n aud: z.literal(HOST_AUDIENCE),\n gid: z.string().min(1),\n htm: z.enum([\"GET\", \"POST\"]),\n htu: z.string().min(1),\n iat: z.number().int(),\n exp: z.number().int(),\n jti: z.string().min(8).max(128),\n});\n\nconst withoutQuery = (url: string): string => {\n const parsed = new URL(url);\n parsed.search = \"\";\n parsed.hash = \"\";\n return parsed.href;\n};\n\nfunction claimJti(\n keys: GrantKeys,\n grantId: string,\n jti: string,\n now: number,\n rememberUntil: number,\n): boolean {\n let seen = replays.get(keys);\n if (!seen) replays.set(keys, (seen = new Map()));\n for (const [id, expiresAt] of seen) {\n if (expiresAt > now) break;\n seen.delete(id);\n }\n const id = `${grantId}:${jti}`;\n if (seen.has(id)) return false;\n while (seen.size >= REPLAY_CACHE_SIZE) seen.delete(seen.keys().next().value as string);\n seen.set(id, rememberUntil);\n return true;\n}\n\nfunction claimsOf(assertion: HostAssertion): { gid: string; kid: string | undefined } {\n try {\n const header = decodeProtectedHeader(assertion);\n const payload = JSON.parse(\n Buffer.from(assertion.split(\".\")[1] ?? \"\", \"base64url\").toString(\"utf8\"),\n ) as { gid?: unknown };\n if (header.typ !== HOST_ASSERTION_TYP || typeof payload.gid !== \"string\") {\n throw new Error(\"not a host assertion\");\n }\n return { gid: payload.gid, kid: header.kid };\n } catch {\n throw new AuthFailure(\"invalid\", \"The host assertion is malformed.\");\n }\n}\n\nexport async function verifyHostAssertion(\n assertion: HostAssertion,\n request: { readonly method: string; readonly url: string },\n keys: GrantKeys,\n now: number,\n): Promise<GrantKey> {\n const { gid, kid } = claimsOf(assertion);\n const grant = await keys.get(asId(\"grant\", gid));\n if (!grant || kid !== grant.kid) {\n throw new AuthFailure(\"invalid\", \"This computer is not connected.\");\n }\n let payload: unknown;\n try {\n const verified = await compactVerify(assertion, await verifyKeyOf(grant), {\n algorithms: [\"ES256\"],\n });\n payload = JSON.parse(new TextDecoder().decode(verified.payload));\n } catch {\n throw new AuthFailure(\n \"invalid\",\n \"The host assertion is not signed by this computer.\",\n );\n }\n const parsed = assertionClaims.safeParse(payload);\n if (!parsed.success)\n throw new AuthFailure(\"invalid\", \"The host assertion is malformed.\");\n const claims = parsed.data;\n if (claims.htm !== request.method) {\n throw new AuthFailure(\"invalid\", \"The host assertion is for another method.\");\n }\n let sameUrl: boolean;\n try {\n sameUrl = withoutQuery(claims.htu) === withoutQuery(request.url);\n } catch {\n sameUrl = false;\n }\n if (!sameUrl)\n throw new AuthFailure(\"invalid\", \"The host assertion is for another URL.\");\n const issuedAt = claims.iat * 1000;\n if (\n claims.exp - claims.iat > HOST_ASSERTION_TTL_MS / 1000 ||\n issuedAt - now > CLOCK_SKEW_MS\n ) {\n throw new AuthFailure(\"invalid\", \"The host assertion has an impossible lifetime.\");\n }\n if (now - issuedAt > HOST_ASSERTION_TTL_MS || claims.exp * 1000 <= now) {\n throw new AuthFailure(\"expired\", \"The host assertion expired.\");\n }\n const acceptableUntil = Math.min(claims.exp * 1000, issuedAt + HOST_ASSERTION_TTL_MS);\n if (!claimJti(keys, grant.grantId, claims.jti, now, acceptableUntil)) {\n throw new AuthFailure(\"invalid\", \"The host assertion was already used.\");\n }\n return grant;\n}\n\nexport function hostPrincipalOf(grant: GrantKey): HostPrincipal {\n return {\n kind: \"host\",\n userId: grant.userId,\n grantId: grant.grantId,\n hostId: grant.hostId,\n };\n}\n\nexport const HOSTS_TAG = HOST_GRANTS_TAG;\n\nexport const HOSTS_MIGRATION: Migration = {\n id: \"auth/0003_hosts\",\n sql: `\n create table parlor_auth_hosts (\n grant_id text primary key,\n host_id text not null unique,\n user_id text not null,\n name text not null,\n platform text not null,\n public_key jsonb not null,\n kid text not null,\n created_at timestamptz not null default now(),\n last_used_at timestamptz\n );\n create index parlor_auth_hosts_user on parlor_auth_hosts (user_id);\n\n create table parlor_auth_host_codes (\n code_hash text primary key,\n user_id text not null,\n code_challenge text not null,\n key_thumbprint text not null,\n redirect_uri text not null,\n host_name text not null,\n platform text not null,\n device_id text,\n expires_at timestamptz not null\n )`,\n};\n\nexport interface ConnectedHost {\n readonly hostId: HostId;\n readonly name: string;\n readonly platform: string;\n readonly connectedAt: string;\n readonly lastUsedAt: string | null;\n}\n\nexport interface HostGrantDeps {\n readonly host: PluginHost;\n readonly settings: ParlorAuthSettings;\n}\n\nfunction databaseOf(host: PluginHost): DataProvider {\n if (!host.database) throw new Error(\"Host grants need a database.\");\n return host.database;\n}\n\ninterface RemovedGrant {\n readonly grant_id: string;\n readonly host_id: string;\n}\n\n/**\n * Deletes the grant's key row and revokes the grant in one transaction. The row must go:\n * `RevocationSet` forgets after its horizon, and a host assertion's `iat` is always fresh.\n */\nasync function removeGrant(\n deps: HostGrantDeps,\n match: { readonly hostId: string } | { readonly grantId: string },\n userId: string,\n): Promise<RemovedGrant | undefined> {\n return databaseOf(deps.host).transaction(async (handle) => {\n const tx = handle as Database;\n const removed = rowsOf<RemovedGrant>(\n await tx.execute(\n \"hostId\" in match\n ? sql`delete from parlor_auth_hosts where host_id = ${match.hostId} and user_id = ${userId} returning grant_id, host_id`\n : sql`delete from parlor_auth_hosts where grant_id = ${match.grantId} and user_id = ${userId} returning grant_id, host_id`,\n ),\n )[0];\n if (!removed) return undefined;\n await RevocationSet.revoke(tx, { kind: \"grant\", id: removed.grant_id });\n return removed;\n });\n}\n\ninterface HostListRow {\n readonly host_id: string;\n readonly name: string;\n readonly platform: string;\n readonly created_at: string | Date;\n readonly last_used_at: string | Date | null;\n}\n\nconst isoOf = (value: string | Date): string => new Date(value).toISOString();\n\n/** `hosts` and `revokeHost`, merged into the account actions once host grants land. */\nexport function hostAccountActions(deps: HostGrantDeps) {\n return createRegistry({\n hosts: defineAction({\n description: \"List the computers connected to this account.\",\n input: z.object({}),\n reads: [HOSTS_TAG],\n run: async (_input, ctx): Promise<ConnectedHost[]> => {\n const user = signedIn(ctx);\n const rows = rowsOf<HostListRow>(\n await (databaseOf(deps.host).read() as Database).execute(sql`\n select host_id, name, platform, created_at, last_used_at from parlor_auth_hosts\n where user_id = ${user.userId} order by created_at, host_id`),\n );\n return rows.map((row) => ({\n hostId: asId(\"host\", row.host_id),\n name: row.name,\n platform: row.platform,\n connectedAt: isoOf(row.created_at),\n lastUsedAt: row.last_used_at === null ? null : isoOf(row.last_used_at),\n }));\n },\n }),\n revokeHost: defineAction({\n description:\n \"Disconnect a computer; its grant, turn tokens and stream end at once.\",\n input: z.object({ hostId: z.string().min(1) }),\n run: async ({ hostId }, ctx): Promise<{ readonly id: string }> => {\n const user = signedIn(ctx);\n const removed = await removeGrant(deps, { hostId }, user.userId);\n if (!removed) throw new ActionError(\"not_found\", `No computer ${hostId}`);\n await deps.host.announce(ctx.scope, [[HOSTS_TAG, hostId]]);\n return { id: hostId };\n },\n }),\n });\n}\n\nexport type HostAccountActions = ActionsOf<ReturnType<typeof hostAccountActions>>;\n\nconst THUMBPRINT = /^[A-Za-z0-9_-]{43}$/;\nconst isPrintable = (text: string) =>\n [...text].every((char) => {\n const code = char.codePointAt(0)!;\n return code >= 0x20 && code !== 0x7f;\n });\nconst LOOPBACK = /^http:\\/\\/127\\.0\\.0\\.1:(\\d{1,5})\\/callback$/;\nconst IPC_REDIRECT = \"urn:parlor:ipc\";\nconst CODE_TTL_MS = 10 * 60_000;\n\nfunction isHostRedirect(value: unknown): value is HostRedirect {\n if (value === IPC_REDIRECT) return true;\n if (typeof value !== \"string\") return false;\n const port = LOOPBACK.exec(value)?.[1];\n return port !== undefined && Number(port) >= 1 && Number(port) <= 65_535;\n}\n\nconst authorizeRequest = z.object({\n redirectUri: z.custom<HostRedirect>(isHostRedirect, \"Use a loopback redirect.\"),\n codeChallenge: z.string().regex(THUMBPRINT),\n state: z.string().min(1).max(256),\n hostName: z\n .string()\n .trim()\n .min(1)\n .max(64)\n .refine(isPrintable, \"Use printable characters.\"),\n platform: z\n .string()\n .trim()\n .min(1)\n .max(32)\n .refine(isPrintable, \"Use printable characters.\"),\n matchingCode: z.string().regex(MATCHING_CODE),\n keyThumbprint: z.string().regex(THUMBPRINT),\n agentTools: z.literal(\"offered\").optional(),\n});\n\nconst authorizeAnswer = authorizeRequest.extend({\n decision: z.enum([\"connect\", \"cancel\"]),\n useAgentTools: z.literal(\"on\").optional(),\n});\n\nconst publicKeySchema = z.looseObject({\n kty: z.literal(\"EC\"),\n crv: z.literal(\"P-256\"),\n x: z.string().regex(THUMBPRINT),\n y: z.string().regex(THUMBPRINT),\n});\n\nconst keyExchange = z.object({\n code: z.string().min(16).max(256),\n codeVerifier: z.string().min(43).max(128),\n publicKey: publicKeySchema,\n proof: z.string().min(1).max(256),\n});\n\nconst MAX_BODY_BYTES = 16 * 1024;\n\nconst sha256 = (text: string, encoding: \"hex\" | \"base64url\") =>\n createHash(\"sha256\").update(text).digest(encoding);\n\nfunction sameText(a: string, b: string): boolean {\n const left = createHash(\"sha256\").update(a).digest();\n const right = createHash(\"sha256\").update(b).digest();\n return timingSafeEqual(left, right);\n}\n\nasync function bodyOf(\n request: Request,\n): Promise<{ readonly json: boolean; readonly fields: unknown }> {\n const text = await readBoundedText(request, MAX_BODY_BYTES);\n if (text === undefined) return { json: false, fields: undefined };\n if ((request.headers.get(\"content-type\") ?? \"\").includes(\"application/json\")) {\n try {\n return { json: true, fields: JSON.parse(text) as unknown };\n } catch {\n return { json: true, fields: undefined };\n }\n }\n return { json: false, fields: Object.fromEntries(new URLSearchParams(text)) };\n}\n\nfunction invalidGrant(): Response {\n return Response.json(\n {\n error: {\n code: \"invalid_grant\",\n message: \"The pairing code is invalid, expired or already used.\",\n },\n },\n { status: 400 },\n );\n}\n\ninterface PairingCode {\n readonly user_id: string;\n readonly code_challenge: string;\n readonly key_thumbprint: string;\n readonly host_name: string;\n readonly platform: string;\n readonly expires_at: string | Date;\n}\n\nasync function verifyProof(\n publicKey: JsonWebKey,\n code: string,\n proof: string,\n): Promise<boolean> {\n try {\n const key = await crypto.subtle.importKey(\"jwk\", publicKey, EC_P256, false, [\n \"verify\",\n ]);\n return await crypto.subtle.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n key,\n Buffer.from(proof, \"base64url\"),\n new TextEncoder().encode(code),\n );\n } catch {\n return false;\n }\n}\n\n/** The MCP server name the host registered the app under, as the connected page shows it. */\nconst AGENT_TOOLS_NAME = /^[a-z0-9][a-z0-9_-]{0,79}$/;\n\nconst KEEP_PAIRING = `try{const s=new URLSearchParams(location.hash.slice(1)).get(${JSON.stringify(HOST_PAIRING_FRAGMENT)});if(s)localStorage.setItem(${JSON.stringify(HOST_PAIRING_KEY)},s)}catch{}history.replaceState(null,\"\",location.pathname)`;\n\n/**\n * `GET|POST /hosts/authorize` is the framework-owned consent page and its answer, `POST\n * /hosts/token` the PKCE exchange binding the host's key, `GET /hosts/connected` where the\n * approving browser lands and keeps the pairing secret, `POST /hosts/revoke` the host\n * disconnecting itself.\n */\nexport function hostRoutes(deps: HostGrantDeps): readonly AnyPluginRoute[] {\n const { host, settings } = deps;\n const appName = () =>\n process.env.PARLOR_APP_NAME ?? settings.appName ?? new URL(settings.origin).host;\n const authorizeUrl = `${host.basePath}/${AUTH_PLUGIN}/hosts/authorize`;\n const connectedUrl = `${host.basePath}/${AUTH_PLUGIN}/hosts/connected`;\n const accountOf = async (userId: UserId) => host.auth?.account?.(userId);\n\n return [\n pluginRoute({\n method: \"GET\",\n path: \"/hosts/authorize\",\n access: [\"user\"],\n handle: async (request, caller) => {\n if (!(await chatAllows(host, caller))) return failure(CHAT_REFUSED, 403);\n const parsed = authorizeRequest.safeParse(\n Object.fromEntries(new URL(request.url).searchParams),\n );\n if (!parsed.success) {\n return failure(\"This connection request is incomplete.\", 400);\n }\n const pairing = parsed.data;\n const profile = await accountOf(caller.principal.userId);\n const app = appName();\n const hidden = Object.entries(pairing)\n .map(\n ([name, value]) =>\n `<input type=\"hidden\" name=\"${name}\" value=\"${escape(String(value))}\">`,\n )\n .join(\"\\n\");\n const body = `\n<h1>Connect ${escape(pairing.hostName)} to ${escape(app)}?</h1>\n<p>Signed in as <strong>${escape(profile?.email ?? profile?.name ?? \"your account\")}</strong>.</p>\n<p>The coding agents on <strong>${escape(pairing.hostName)}</strong> (${escape(pairing.platform)}) will take your prompts from ${escape(app)} and run on that computer. Continue only if you just ran <code>connect</code> there.</p>\n<form method=\"post\" action=\"${escape(authorizeUrl)}\">\n${hidden}\n${\n pairing.agentTools === \"offered\"\n ? `<label class=\"choice\"><input type=\"checkbox\" name=\"useAgentTools\" value=\"on\" checked><span>Also let Claude Code and Codex on this computer use ${escape(app)} when you name it. They ask before their first change in each conversation.</span></label>`\n : \"\"\n}\n<button type=\"submit\" name=\"decision\" value=\"cancel\">Cancel</button>\n<button type=\"submit\" name=\"decision\" value=\"connect\">Connect</button>\n</form>`;\n const target =\n pairing.redirectUri === IPC_REDIRECT\n ? []\n : [new URL(pairing.redirectUri).origin];\n return page(\"Connect a computer\", body, [\"'self'\", ...target]);\n },\n }),\n pluginRoute({\n method: \"POST\",\n path: \"/hosts/authorize\",\n access: [\"user\"],\n handle: async (request, caller) => {\n const { json, fields } = await bodyOf(request);\n const refuse = (status: number, code: string, message: string) =>\n json\n ? Response.json({ error: { code, message } }, { status })\n : failure(message, status);\n const origin = request.headers.get(\"origin\");\n if (\n origin !== settings.origin &&\n !(origin && [...SHELL_ORIGINS, ...devOrigins()].includes(origin))\n ) {\n return refuse(\n 403,\n \"forbidden\",\n \"This answer did not come from the consent page.\",\n );\n }\n if (!(await chatAllows(host, caller))) {\n return refuse(403, \"forbidden\", CHAT_REFUSED);\n }\n const parsed = authorizeAnswer.safeParse(fields);\n if (!parsed.success) {\n return refuse(400, \"invalid_input\", \"This connection request is incomplete.\");\n }\n const { decision, useAgentTools, ...pairing } = parsed.data;\n const target =\n pairing.redirectUri === IPC_REDIRECT ? undefined : new URL(pairing.redirectUri);\n if (decision === \"cancel\") {\n if (!target)\n return Response.json({ error: \"access_denied\", state: pairing.state });\n target.searchParams.set(\"error\", \"access_denied\");\n target.searchParams.set(\"state\", pairing.state);\n return new Response(null, { status: 303, headers: { location: target.href } });\n }\n const code = randomBytes(32).toString(\"base64url\");\n await databaseOf(host).transaction(async (handle) => {\n const tx = handle as Database;\n await tx.execute(\n sql`delete from parlor_auth_host_codes where expires_at < ${new Date().toISOString()}`,\n );\n await tx.execute(sql`\n insert into parlor_auth_host_codes\n (code_hash, user_id, code_challenge, key_thumbprint, redirect_uri, host_name, platform, expires_at)\n values (${sha256(code, \"hex\")}, ${caller.principal.userId}, ${pairing.codeChallenge},\n ${pairing.keyThumbprint}, ${pairing.redirectUri}, ${pairing.hostName}, ${pairing.platform},\n ${new Date(Date.now() + CODE_TTL_MS).toISOString()})`);\n });\n const agentTools =\n pairing.agentTools === \"offered\" ? useAgentTools === \"on\" : undefined;\n if (!target) {\n return Response.json({\n code,\n state: pairing.state,\n ...(agentTools === undefined ? {} : { agentTools }),\n });\n }\n target.searchParams.set(\"code\", code);\n target.searchParams.set(\"state\", pairing.state);\n if (agentTools !== undefined)\n target.searchParams.set(\"agentTools\", agentTools ? \"on\" : \"off\");\n return new Response(null, { status: 303, headers: { location: target.href } });\n },\n }),\n {\n method: \"POST\",\n path: \"/hosts/token\",\n access: \"public\",\n handle: async (request) => {\n const { fields } = await bodyOf(request);\n const exchange = keyExchange.safeParse(fields);\n if (!exchange.success || \"d\" in exchange.data.publicKey) return invalidGrant();\n const { code, codeVerifier, proof } = exchange.data;\n const { kty, crv, x, y } = exchange.data.publicKey;\n const publicKey: JsonWebKey = { kty, crv, x, y };\n const database = databaseOf(host);\n const stored = await database.transaction(\n async (handle) =>\n rowsOf<PairingCode>(\n await (handle as Database).execute(sql`\n delete from parlor_auth_host_codes where code_hash = ${sha256(code, \"hex\")}\n returning user_id, code_challenge, key_thumbprint, host_name, platform, expires_at`),\n )[0],\n );\n if (\n !stored ||\n new Date(stored.expires_at).getTime() <= Date.now() ||\n !sameText(sha256(codeVerifier, \"base64url\"), stored.code_challenge) ||\n !sameText(\n await calculateJwkThumbprint(publicKey, \"sha256\"),\n stored.key_thumbprint,\n ) ||\n !(await verifyProof(publicKey, code, proof))\n ) {\n return invalidGrant();\n }\n const grantId = asId(\"grant\", `host:${crypto.randomUUID()}`);\n const hostId = asId(\"host\", crypto.randomUUID());\n const userId = asId(\"user\", stored.user_id);\n await database.transaction(async (handle) => {\n await (handle as Database).execute(sql`\n insert into parlor_auth_hosts (grant_id, host_id, user_id, name, platform, public_key, kid)\n values (${grantId}, ${hostId}, ${userId}, ${stored.host_name}, ${stored.platform},\n ${JSON.stringify(publicKey)}::jsonb, ${stored.key_thumbprint})`);\n });\n await host.announce(userId, [[HOSTS_TAG, hostId]]);\n const profile = await accountOf(userId);\n const response: HostGrantResponse = {\n grant: { id: grantId, hostId },\n account: { userId, name: profile?.name ?? \"\", email: profile?.email },\n landing: connectedUrl,\n };\n return Response.json(response);\n },\n },\n {\n method: \"GET\",\n path: \"/hosts/connected\",\n access: \"public\",\n handle: async (request) => {\n const app = escape(appName());\n const tools = new URL(request.url).searchParams.get(\"agentTools\");\n const body =\n tools && AGENT_TOOLS_NAME.test(tools)\n ? `<h1>Connected to ${app}</h1>\n<p>Use it two ways:</p>\n<ul>\n<li>In the agent sidebar of ${app}.</li>\n<li>In Claude Code or Codex on this computer: ask them to “use <code>${escape(tools)}</code> to …”. They ask you before their first change in each conversation.</li>\n</ul>\n<p>You can close this tab.</p>`\n : `<h1>Connected to ${app}</h1>\n<p>The coding agents on your computer are ready in the agent sidebar of ${app}. You can close this tab.</p>`;\n return page(\"Computer connected\", body, [\"'none'\"], KEEP_PAIRING);\n },\n },\n pluginRoute({\n method: \"POST\",\n path: \"/hosts/devices/link\",\n access: [\"host\"],\n handle: async (request, caller) => {\n if (!(await chatAllows(host, caller))) {\n return Response.json(\n { error: { code: \"forbidden\", message: CHAT_REFUSED } },\n { status: 403 },\n );\n }\n const { fields } = await bodyOf(request);\n const code =\n z.object({ code: z.string().max(32) }).safeParse(fields).data?.code ?? \"\";\n const found = await findPendingDevice(databaseOf(host), caller.principal.userId, {\n code,\n });\n if (!found) {\n return Response.json(\n {\n error: {\n code: \"not_found\",\n message:\n \"No device of this account shows that code. Check it, or show a new code on the device.\",\n },\n },\n { status: 404 },\n );\n }\n return Response.json(found);\n },\n }),\n pluginRoute({\n method: \"POST\",\n path: \"/hosts/revoke\",\n access: [\"host\"],\n handle: async (_request, caller) => {\n const { userId, grantId } = caller.principal;\n const removed = await removeGrant(deps, { grantId }, userId);\n if (removed) await host.announce(caller.scope, [[HOSTS_TAG, removed.host_id]]);\n return Response.json({ id: grantId });\n },\n }),\n ];\n}\n"]}
package/dist/pages.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export declare const escape: (text: string) => string;
2
- export declare function page(title: string, body: string, formAction: readonly string[]): Response;
2
+ export declare function page(title: string, body: string, formAction: readonly string[], script?: string): Response;
3
3
  export declare function failure(message: string, status: number): Response;
4
4
  //# sourceMappingURL=pages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,SAAU,MAAM,WAKhC,CAAC;AAsBJ,wBAAgB,IAAI,CAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,QAAQ,CA2BV;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAOjE"}
1
+ {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,SAAU,MAAM,WAKhC,CAAC;AA0BJ,wBAAgB,IAAI,CAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,MAAM,CAAC,EAAE,MAAM,GACd,QAAQ,CA4BV;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAOjE"}
package/dist/pages.js CHANGED
@@ -12,13 +12,16 @@ ul { margin: 0 0 20px; padding-left: 20px; }
12
12
  li { margin-bottom: 6px; }
13
13
  strong { color: var(--text); font-weight: 600; }
14
14
  code { font: 0.9em ui-monospace, "SF Mono", Menlo, monospace; color: var(--text); }
15
- form { display: flex; gap: 8px; justify-content: flex-end; margin: 0; }
15
+ form { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; margin: 0; }
16
+ label.choice { flex-basis: 100%; display: flex; gap: 10px; align-items: flex-start; margin: 4px 0 12px; color: var(--muted); font-size: 14px; cursor: pointer; }
17
+ label.choice input { margin: 3px 0 0; accent-color: var(--accent); }
16
18
  button { font: inherit; font-weight: 600; padding: 9px 18px; border-radius: 8px; border: 1px solid var(--line); background: transparent; color: var(--text); cursor: pointer; }
17
19
  button[value="true"], button[value="connect"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
18
20
  button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
19
21
  `;
20
- const STYLE_HASH = createHash("sha256").update(STYLE).digest("base64");
21
- export function page(title, body, formAction) {
22
+ const sha256 = (text) => createHash("sha256").update(text).digest("base64");
23
+ const STYLE_HASH = sha256(STYLE);
24
+ export function page(title, body, formAction, script) {
22
25
  const html = `<!doctype html>
23
26
  <html lang="en">
24
27
  <head>
@@ -27,7 +30,7 @@ export function page(title, body, formAction) {
27
30
  <title>${escape(title)}</title>
28
31
  <style>${STYLE}</style>
29
32
  </head>
30
- <body><main>${body}</main></body>
33
+ <body><main>${body}</main>${script ? `<script>${script}</script>` : ""}</body>
31
34
  </html>`;
32
35
  return new Response(html, {
33
36
  headers: {
@@ -36,6 +39,7 @@ export function page(title, body, formAction) {
36
39
  "content-security-policy": [
37
40
  "default-src 'none'",
38
41
  `style-src 'sha256-${STYLE_HASH}'`,
42
+ ...(script ? [`script-src 'sha256-${sha256(script)}'`] : []),
39
43
  `form-action ${formAction.join(" ")}`,
40
44
  "frame-ancestors 'none'",
41
45
  "base-uri 'none'",
package/dist/pages.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pages.js","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CACrC,IAAI,CAAC,OAAO,CACV,UAAU,EACV,CAAC,IAAI,EAAE,EAAE,CACP,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,CAAE,CACnF,CAAC;AAEJ,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;CAgBb,CAAC;AAEF,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEvE,MAAM,UAAU,IAAI,CAClB,KAAa,EACb,IAAY,EACZ,UAA6B;IAE7B,MAAM,IAAI,GAAG;;;;;SAKN,MAAM,CAAC,KAAK,CAAC;SACb,KAAK;;cAEA,IAAI;QACV,CAAC;IACP,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;QACxB,OAAO,EAAE;YACP,cAAc,EAAE,0BAA0B;YAC1C,eAAe,EAAE,UAAU;YAC3B,yBAAyB,EAAE;gBACzB,oBAAoB;gBACpB,qBAAqB,UAAU,GAAG;gBAClC,eAAe,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;gBACrC,wBAAwB;gBACxB,iBAAiB;aAClB,CAAC,IAAI,CAAC,IAAI,CAAC;YACZ,wBAAwB,EAAE,SAAS;YACnC,6DAA6D;YAC7D,iBAAiB,EAAE,aAAa;SACjC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,MAAc;IACrD,MAAM,QAAQ,GAAG,IAAI,CACnB,sBAAsB,EACtB,mCAAmC,MAAM,CAAC,OAAO,CAAC,MAAM,EACxD,CAAC,QAAQ,CAAC,CACX,CAAC;IACF,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;AAC5E,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\n\nexport const escape = (text: string) =>\n text.replace(\n /[&<>\"']/g,\n (char) =>\n ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[char]!,\n );\n\nconst STYLE = `\n:root { color-scheme: light dark; --bg: #f6f6f4; --card: #fff; --text: #1d1d1b; --muted: #5f5f5a; --line: #e2e2dc; --accent: #1d1d1b; --on-accent: #fff; }\n@media (prefers-color-scheme: dark) { :root { --bg: #151514; --card: #1f1f1d; --text: #ededea; --muted: #a3a39d; --line: #34342f; --accent: #ededea; --on-accent: #151514; } }\n* { box-sizing: border-box; }\nbody { margin: 0; min-height: 100vh; display: grid; place-items: center; padding: 16px; background: var(--bg); color: var(--text); font: 15px/1.5 system-ui, -apple-system, \"Segoe UI\", sans-serif; }\nmain { width: 100%; max-width: 420px; background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 28px; }\nh1 { font-size: 20px; line-height: 1.3; margin: 0 0 8px; }\np { margin: 0 0 12px; color: var(--muted); }\nul { margin: 0 0 20px; padding-left: 20px; }\nli { margin-bottom: 6px; }\nstrong { color: var(--text); font-weight: 600; }\ncode { font: 0.9em ui-monospace, \"SF Mono\", Menlo, monospace; color: var(--text); }\nform { display: flex; gap: 8px; justify-content: flex-end; margin: 0; }\nbutton { font: inherit; font-weight: 600; padding: 9px 18px; border-radius: 8px; border: 1px solid var(--line); background: transparent; color: var(--text); cursor: pointer; }\nbutton[value=\"true\"], button[value=\"connect\"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }\nbutton:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n`;\n\nconst STYLE_HASH = createHash(\"sha256\").update(STYLE).digest(\"base64\");\n\nexport function page(\n title: string,\n body: string,\n formAction: readonly string[],\n): Response {\n const html = `<!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<title>${escape(title)}</title>\n<style>${STYLE}</style>\n</head>\n<body><main>${body}</main></body>\n</html>`;\n return new Response(html, {\n headers: {\n \"content-type\": \"text/html; charset=utf-8\",\n \"cache-control\": \"no-store\",\n \"content-security-policy\": [\n \"default-src 'none'\",\n `style-src 'sha256-${STYLE_HASH}'`,\n `form-action ${formAction.join(\" \")}`,\n \"frame-ancestors 'none'\",\n \"base-uri 'none'\",\n ].join(\"; \"),\n \"x-content-type-options\": \"nosniff\",\n // no-referrer would make the form POST carry `Origin: null`.\n \"referrer-policy\": \"same-origin\",\n },\n });\n}\n\nexport function failure(message: string, status: number): Response {\n const response = page(\n \"Authorization failed\",\n `<h1>Authorization failed</h1><p>${escape(message)}</p>`,\n [\"'none'\"],\n );\n return new Response(response.body, { status, headers: response.headers });\n}\n"]}
1
+ {"version":3,"file":"pages.js","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CACrC,IAAI,CAAC,OAAO,CACV,UAAU,EACV,CAAC,IAAI,EAAE,EAAE,CACP,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,CAAE,CACnF,CAAC;AAEJ,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;CAkBb,CAAC;AAEF,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEpF,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;AAEjC,MAAM,UAAU,IAAI,CAClB,KAAa,EACb,IAAY,EACZ,UAA6B,EAC7B,MAAe;IAEf,MAAM,IAAI,GAAG;;;;;SAKN,MAAM,CAAC,KAAK,CAAC;SACb,KAAK;;cAEA,IAAI,UAAU,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,WAAW,CAAC,CAAC,CAAC,EAAE;QAC9D,CAAC;IACP,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;QACxB,OAAO,EAAE;YACP,cAAc,EAAE,0BAA0B;YAC1C,eAAe,EAAE,UAAU;YAC3B,yBAAyB,EAAE;gBACzB,oBAAoB;gBACpB,qBAAqB,UAAU,GAAG;gBAClC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,sBAAsB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D,eAAe,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;gBACrC,wBAAwB;gBACxB,iBAAiB;aAClB,CAAC,IAAI,CAAC,IAAI,CAAC;YACZ,wBAAwB,EAAE,SAAS;YACnC,6DAA6D;YAC7D,iBAAiB,EAAE,aAAa;SACjC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,MAAc;IACrD,MAAM,QAAQ,GAAG,IAAI,CACnB,sBAAsB,EACtB,mCAAmC,MAAM,CAAC,OAAO,CAAC,MAAM,EACxD,CAAC,QAAQ,CAAC,CACX,CAAC;IACF,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;AAC5E,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\n\nexport const escape = (text: string) =>\n text.replace(\n /[&<>\"']/g,\n (char) =>\n ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[char]!,\n );\n\nconst STYLE = `\n:root { color-scheme: light dark; --bg: #f6f6f4; --card: #fff; --text: #1d1d1b; --muted: #5f5f5a; --line: #e2e2dc; --accent: #1d1d1b; --on-accent: #fff; }\n@media (prefers-color-scheme: dark) { :root { --bg: #151514; --card: #1f1f1d; --text: #ededea; --muted: #a3a39d; --line: #34342f; --accent: #ededea; --on-accent: #151514; } }\n* { box-sizing: border-box; }\nbody { margin: 0; min-height: 100vh; display: grid; place-items: center; padding: 16px; background: var(--bg); color: var(--text); font: 15px/1.5 system-ui, -apple-system, \"Segoe UI\", sans-serif; }\nmain { width: 100%; max-width: 420px; background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 28px; }\nh1 { font-size: 20px; line-height: 1.3; margin: 0 0 8px; }\np { margin: 0 0 12px; color: var(--muted); }\nul { margin: 0 0 20px; padding-left: 20px; }\nli { margin-bottom: 6px; }\nstrong { color: var(--text); font-weight: 600; }\ncode { font: 0.9em ui-monospace, \"SF Mono\", Menlo, monospace; color: var(--text); }\nform { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; margin: 0; }\nlabel.choice { flex-basis: 100%; display: flex; gap: 10px; align-items: flex-start; margin: 4px 0 12px; color: var(--muted); font-size: 14px; cursor: pointer; }\nlabel.choice input { margin: 3px 0 0; accent-color: var(--accent); }\nbutton { font: inherit; font-weight: 600; padding: 9px 18px; border-radius: 8px; border: 1px solid var(--line); background: transparent; color: var(--text); cursor: pointer; }\nbutton[value=\"true\"], button[value=\"connect\"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }\nbutton:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n`;\n\nconst sha256 = (text: string) => createHash(\"sha256\").update(text).digest(\"base64\");\n\nconst STYLE_HASH = sha256(STYLE);\n\nexport function page(\n title: string,\n body: string,\n formAction: readonly string[],\n script?: string,\n): Response {\n const html = `<!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<title>${escape(title)}</title>\n<style>${STYLE}</style>\n</head>\n<body><main>${body}</main>${script ? `<script>${script}</script>` : \"\"}</body>\n</html>`;\n return new Response(html, {\n headers: {\n \"content-type\": \"text/html; charset=utf-8\",\n \"cache-control\": \"no-store\",\n \"content-security-policy\": [\n \"default-src 'none'\",\n `style-src 'sha256-${STYLE_HASH}'`,\n ...(script ? [`script-src 'sha256-${sha256(script)}'`] : []),\n `form-action ${formAction.join(\" \")}`,\n \"frame-ancestors 'none'\",\n \"base-uri 'none'\",\n ].join(\"; \"),\n \"x-content-type-options\": \"nosniff\",\n // no-referrer would make the form POST carry `Origin: null`.\n \"referrer-policy\": \"same-origin\",\n },\n });\n}\n\nexport function failure(message: string, status: number): Response {\n const response = page(\n \"Authorization failed\",\n `<h1>Authorization failed</h1><p>${escape(message)}</p>`,\n [\"'none'\"],\n );\n return new Response(response.body, { status, headers: response.headers });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAaA,OAAO,EAGL,KAAK,YAAY,EAOlB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAwDjE,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7C,QAAQ,CAAC,GAAG,EAAE;QACZ,UAAU,CAAC,KAAK,EAAE;YAAE,OAAO,EAAE,OAAO,CAAA;SAAE,GAAG,OAAO,CAAC;YAC/C,QAAQ,CAAC,OAAO,EAAE;gBAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;gBAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;aAAE,CAAC;YACnE,QAAQ,CAAC,IAAI,EAAE;gBACb,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;gBACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;aACxB,CAAC;SACH,GAAG,IAAI,CAAC,CAAC;KACX,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC/C;AAED,UAAU,KAAK;IACb,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,YAAY,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC3E,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAA;SAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;QACrE,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,KAAK,EAAE,CAAA;SAAE,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACxE,UAAU,CAAC,KAAK,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,KAAK,EAAE,CAAA;SAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;KACvE,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,EAAE;QACxB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;QACvD,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KAC7C,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CAChD;AAED,MAAM,MAAM,yBAAyB,GACjC;IAAE,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAA;CAAE,GACzC;IACE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;CACrC,CAAC;AAuBN;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,YAAY,CAkTpF"}
package/dist/provider.js CHANGED
@@ -12,7 +12,7 @@ import { createGrantKeys, hostAccountActions, hostPrincipalOf, HOSTS_MIGRATION,
12
12
  import { AUTH_MIGRATIONS } from "./migrations.js";
13
13
  import { RevocationSet } from "./revocation.js";
14
14
  import { authRoutes } from "./routes.js";
15
- import { agentPrincipalOf, credentialOf, delegate, verifyTurnToken, } from "./tokens.js";
15
+ import { agentPrincipalOf, credentialOf, delegate, delegateAgent, outsideAgentPrincipalOf, verifyAgentToken, verifyTurnToken, } from "./tokens.js";
16
16
  import { createTurnKeyStore, TURN_KEYS_MIGRATION, } from "./turn-keys.js";
17
17
  /** Stands in for the instance until the first call needs it. */
18
18
  function deferredInstance(options) {
@@ -174,6 +174,19 @@ export function betterAuthProvider(provided) {
174
174
  }
175
175
  return agentPrincipalOf(claims);
176
176
  };
177
+ const outsideAgentOf = async (token) => {
178
+ const store = installed().turnKeys;
179
+ let turnTokenKeys = await store.keys();
180
+ const kid = decodeProtectedHeader(token).kid;
181
+ if (kid !== undefined && !turnTokenKeys.publicKeys.has(kid)) {
182
+ turnTokenKeys = await store.refresh();
183
+ }
184
+ const claims = await verifyAgentToken(turnTokenKeys, token, Date.now());
185
+ if (await started().isRevoked({ kind: "grant", id: claims.gid })) {
186
+ throw new AuthFailure("revoked", "This computer was disconnected.");
187
+ }
188
+ return outsideAgentPrincipalOf(claims);
189
+ };
177
190
  const authenticateRequest = async (request) => {
178
191
  await ready();
179
192
  const credential = credentialOf(request.headers.get("authorization"));
@@ -182,6 +195,8 @@ export function betterAuthProvider(provided) {
182
195
  return hostOf(request, credential.assertion);
183
196
  case "turn":
184
197
  return turnOf(credential.token);
198
+ case "agent":
199
+ return outsideAgentOf(credential.token);
185
200
  case "access":
186
201
  return agentOf(credential.token);
187
202
  case "session": {
@@ -264,6 +279,10 @@ export function betterAuthProvider(provided) {
264
279
  await ready();
265
280
  return delegate(await installed().turnKeys.keys(), host, turn, Date.now());
266
281
  },
282
+ async delegateAgent(host, agent) {
283
+ await ready();
284
+ return delegateAgent(await installed().turnKeys.keys(), host, agent, Date.now());
285
+ },
267
286
  async hostActive(grantId) {
268
287
  const revoked = await started().isRevoked({ kind: "grant", id: grantId });
269
288
  return !revoked && (await installed().grantKeys.get(grantId)) !== undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AgentPrincipal,\n ANONYMOUS,\n asId,\n type AuthenticatedPrincipal,\n type DeviceId,\n type GrantId,\n type HostPrincipal,\n type Principal,\n type UserId,\n type UserPrincipal,\n} from \"@parlor/core\";\nimport { createRegistry } from \"@parlor/core/registry\";\nimport {\n type AccountProfile,\n AuthFailure,\n type AuthProvider,\n type Delegation,\n type DeviceKeys,\n type PluginHost,\n REVOCATION_HORIZON_MS,\n type TurnDelegation,\n} from \"@parlor/server\";\nimport { betterAuth, type BetterAuthOptions } from \"better-auth\";\nimport {\n createLocalJWKSet,\n decodeProtectedHeader,\n errors,\n type JSONWebKeySet,\n type JWTPayload,\n jwtVerify,\n} from \"jose\";\n\nimport { accountActions } from \"./account.js\";\nimport { AUDIT_MIGRATION, createAuditLog } from \"./audit.js\";\nimport {\n AUTH_PLUGIN,\n bridgeOf,\n MCP_SCOPE,\n type ParlorAuthSettings,\n} from \"./better-auth.js\";\nimport {\n createDeviceRegistry,\n type DeviceRegistry,\n deviceAccountActions,\n DEVICE_LINKING_MIGRATION,\n DEVICES_MIGRATION,\n} from \"./devices.js\";\nimport { grantIdOf } from \"./grants.js\";\nimport {\n createGrantKeys,\n type GrantKeys,\n hostAccountActions,\n hostPrincipalOf,\n HOSTS_MIGRATION,\n hostRoutes,\n verifyHostAssertion,\n} from \"./hosts.js\";\nimport { AUTH_MIGRATIONS } from \"./migrations.js\";\nimport { RevocationSet } from \"./revocation.js\";\nimport { authRoutes } from \"./routes.js\";\nimport {\n agentPrincipalOf,\n credentialOf,\n delegate,\n type HostAssertion,\n type TurnToken,\n verifyTurnToken,\n} from \"./tokens.js\";\nimport {\n createTurnKeyStore,\n TURN_KEYS_MIGRATION,\n type TurnKeyStore,\n} from \"./turn-keys.js\";\n\n/** The slice of a Better Auth instance Parlor relies on. */\nexport interface BetterAuthInstance {\n readonly options: BetterAuthOptions;\n handler(request: Request): Promise<Response>;\n readonly api: {\n getSession(input: { headers: Headers }): Promise<{\n readonly session: { readonly id: string; readonly userId: string };\n readonly user: {\n readonly id: string;\n readonly name: string;\n readonly email: string;\n };\n } | null>;\n };\n readonly $context: Promise<BetterAuthContext>;\n}\n\ninterface Where {\n readonly field: string;\n readonly value: string;\n}\n\nexport interface BetterAuthContext {\n readonly authCookies: { readonly sessionToken: { readonly name: string } };\n readonly adapter: {\n findMany<T>(input: { model: string; where?: Where[] }): Promise<T[]>;\n findOne<T>(input: { model: string; where: Where[] }): Promise<T | null>;\n deleteMany(input: { model: string; where: Where[] }): Promise<number>;\n };\n readonly secret: string;\n readonly internalAdapter: {\n listSessions(userId: string): Promise<StoredSession[]>;\n deleteSession(token: string): Promise<void>;\n };\n}\n\nexport interface StoredSession {\n readonly id: string;\n readonly token: string;\n readonly userId: string;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n readonly expiresAt: Date;\n readonly ipAddress?: string | null | undefined;\n readonly userAgent?: string | null | undefined;\n}\n\nexport type BetterAuthProviderOptions =\n | { readonly instance: BetterAuthInstance }\n | {\n /**\n * The options for `betterAuth()`, which the provider calls on the first request.\n * Better Auth starts querying the database as soon as it is created, and some\n * runtimes, such as Cloudflare's, allow no I/O while the app loads.\n */\n readonly options: BetterAuthOptions;\n };\n\n/** Stands in for the instance until the first call needs it. */\nfunction deferredInstance(options: BetterAuthOptions): BetterAuthInstance {\n let created: BetterAuthInstance | undefined;\n const current = () =>\n (created ??= betterAuth(options) as unknown as BetterAuthInstance);\n return {\n options,\n handler: (request) => current().handler(request),\n api: { getSession: (input) => current().api.getSession(input) },\n get $context() {\n return current().$context;\n },\n };\n}\n\nfunction hasCookie(request: Request, name: string): boolean {\n const cookie = request.headers.get(\"cookie\");\n if (!cookie) return false;\n return cookie.split(\";\").some((part) => part.trim().startsWith(`${name}=`));\n}\n\n/**\n * Sessions become user principals: a cookie on the same-origin web, a bearer token in\n * native shells. Access tokens Better Auth issued to MCP clients become agent principals\n * without a turn.\n */\nexport function betterAuthProvider(provided: BetterAuthProviderOptions): AuthProvider {\n const instance =\n \"instance\" in provided ? provided.instance : deferredInstance(provided.options);\n const bridge = bridgeOf(instance.options);\n const settings: ParlorAuthSettings = bridge.settings;\n let revocations: RevocationSet | undefined;\n let keys: ReturnType<typeof createLocalJWKSet> | undefined;\n let grantKeys: GrantKeys | undefined;\n let turnKeys: TurnKeyStore | undefined;\n let devices: DeviceRegistry | undefined;\n const clientNames = new Map<string, Promise<string>>();\n const authenticatedAt = new WeakMap<object, number>();\n\n const installed = () => {\n if (!grantKeys || !turnKeys || !devices) {\n throw new Error(\"The auth provider is not installed.\");\n }\n return { grantKeys, turnKeys, devices };\n };\n\n const started = () => {\n if (!revocations) throw new Error(\"The auth provider is not installed.\");\n return revocations;\n };\n\n let preparingTurnKeys = false;\n const ready = async (): Promise<void> => {\n await started().ready();\n if (!preparingTurnKeys) {\n preparingTurnKeys = true;\n installed()\n .turnKeys.keys()\n .catch(() => {\n preparingTurnKeys = false;\n });\n }\n };\n\n const loadKeys = async () => {\n const response = await instance.handler(new Request(`${settings.baseURL}/jwks`));\n if (!response.ok)\n throw new Error(`Better Auth answered /jwks with ${response.status}`);\n return createLocalJWKSet((await response.json()) as JSONWebKeySet);\n };\n\n const verify = async (token: string): Promise<JWTPayload> => {\n const options = {\n issuer: settings.baseURL,\n audience: settings.resource,\n typ: \"at+jwt\",\n };\n keys ??= await loadKeys();\n try {\n return (await jwtVerify(token, keys, options)).payload;\n } catch (error) {\n if (!(error instanceof errors.JWKSNoMatchingKey)) throw error;\n keys = await loadKeys();\n return (await jwtVerify(token, keys, options)).payload;\n }\n };\n\n const clientName = (clientId: string): Promise<string> => {\n let name = clientNames.get(clientId);\n if (!name) {\n name = instance.$context\n .then((context) =>\n context.adapter.findOne<{ name?: string | null }>({\n model: \"oauthClient\",\n where: [{ field: \"clientId\", value: clientId }],\n }),\n )\n .then((client) => client?.name || clientId);\n name.catch(() => clientNames.delete(clientId));\n clientNames.set(clientId, name);\n }\n return name;\n };\n\n const agentOf = async (token: string): Promise<AgentPrincipal> => {\n let payload: JWTPayload;\n try {\n payload = await verify(token);\n } catch (error) {\n if (error instanceof errors.JWTExpired) {\n throw new AuthFailure(\"expired\", \"The access token expired.\");\n }\n throw new AuthFailure(\"invalid\", \"The access token is invalid.\");\n }\n const { sub, iat } = payload;\n const clientId = payload.client_id;\n const scopes = typeof payload.scope === \"string\" ? payload.scope.split(\" \") : [];\n if (typeof sub !== \"string\" || typeof clientId !== \"string\" || iat === undefined) {\n throw new AuthFailure(\"invalid\", \"The access token is missing claims.\");\n }\n if (!scopes.includes(MCP_SCOPE)) {\n throw new AuthFailure(\n \"invalid\",\n `The access token lacks the \"${MCP_SCOPE}\" scope.`,\n );\n }\n const grantId = grantIdOf(sub, clientId);\n if (await started().isRevoked({ kind: \"grant\", id: grantId }, iat * 1000)) {\n throw new AuthFailure(\"revoked\", \"Access for this agent was revoked.\");\n }\n return {\n kind: \"agent\",\n userId: asId(\"user\", sub),\n grantId,\n agent: {\n name: await clientName(clientId),\n verified: clientId.startsWith(\"https://\"),\n },\n };\n };\n\n const userOf = async (request: Request): Promise<UserPrincipal | undefined> => {\n const found = await instance.api.getSession({ headers: request.headers });\n if (!found) return undefined;\n return {\n kind: \"user\",\n userId: asId(\"user\", found.user.id),\n sessionId: found.session.id,\n };\n };\n\n const publicUrlOf = (request: Request): string =>\n new URL(new URL(request.url).pathname, settings.origin).href;\n\n const hostOf = async (\n request: Request,\n assertion: HostAssertion,\n ): Promise<HostPrincipal> => {\n const grant = await verifyHostAssertion(\n assertion,\n { method: request.method, url: publicUrlOf(request) },\n installed().grantKeys,\n Date.now(),\n );\n if (await started().isRevoked({ kind: \"grant\", id: grant.grantId })) {\n throw new AuthFailure(\"revoked\", \"This computer was disconnected.\");\n }\n return hostPrincipalOf(grant);\n };\n\n const turnOf = async (token: TurnToken): Promise<AgentPrincipal> => {\n const store = installed().turnKeys;\n let turnTokenKeys = await store.keys();\n const kid = decodeProtectedHeader(token).kid;\n if (kid !== undefined && !turnTokenKeys.publicKeys.has(kid)) {\n turnTokenKeys = await store.refresh();\n }\n const claims = await verifyTurnToken(turnTokenKeys, token, Date.now());\n if (await started().isRevoked({ kind: \"grant\", id: claims.gid })) {\n throw new AuthFailure(\"revoked\", \"This computer was disconnected.\");\n }\n return agentPrincipalOf(claims);\n };\n\n const authenticateRequest = async (request: Request): Promise<Principal> => {\n await ready();\n const credential = credentialOf(request.headers.get(\"authorization\"));\n switch (credential?.kind) {\n case \"host\":\n return hostOf(request, credential.assertion);\n case \"turn\":\n return turnOf(credential.token);\n case \"access\":\n return agentOf(credential.token);\n case \"session\": {\n const user = await userOf(request);\n if (!user)\n throw new AuthFailure(\"invalid\", \"The session is invalid or has ended.\");\n return user;\n }\n case undefined:\n break;\n }\n const { authCookies } = await instance.$context;\n if (!hasCookie(request, authCookies.sessionToken.name)) return ANONYMOUS;\n return (await userOf(request)) ?? ANONYMOUS;\n };\n\n return {\n name: AUTH_PLUGIN,\n migrations: [\n ...AUTH_MIGRATIONS,\n HOSTS_MIGRATION,\n DEVICES_MIGRATION,\n TURN_KEYS_MIGRATION,\n AUDIT_MIGRATION,\n DEVICE_LINKING_MIGRATION,\n ],\n enforcing: true,\n setup(host: PluginHost) {\n const { database } = host;\n if (!database) throw new Error(\"The auth plugin needs a database.\");\n const set = new RevocationSet({\n database,\n horizonMs: REVOCATION_HORIZON_MS,\n });\n revocations = set;\n const auditLog = createAuditLog(database);\n bridge.revoke = (notice) =>\n database.transaction((tx) => RevocationSet.revoke(tx, notice));\n grantKeys = createGrantKeys(database);\n devices = createDeviceRegistry(database);\n turnKeys = createTurnKeyStore({\n database,\n issuer: settings.baseURL,\n secret: async () => (await instance.$context).secret,\n });\n const hostDeps = {\n host,\n settings,\n };\n return {\n actions: createRegistry({\n ...accountActions({ instance, host, revoke: bridge.revoke }).actions,\n ...hostAccountActions(hostDeps).actions,\n ...deviceAccountActions({ host, registry: devices }).actions,\n }),\n routes: [...authRoutes({ instance, settings, host }), ...hostRoutes(hostDeps)],\n audit: (record) => auditLog.record(record),\n close: async () => {\n await Promise.all([set.stop(), auditLog.stop()]);\n },\n };\n },\n async authenticate(request: Request): Promise<Principal> {\n const startedAt = Date.now();\n const principal = await authenticateRequest(request);\n if (principal.kind !== \"anonymous\") authenticatedAt.set(principal, startedAt);\n return principal;\n },\n challenge(): Response {\n const metadata = `${settings.origin}/.well-known/oauth-protected-resource${new URL(settings.resource).pathname}`;\n return Response.json(\n { error: { code: \"unauthenticated\", message: \"Sign in through OAuth first.\" } },\n {\n status: 401,\n headers: {\n \"www-authenticate\": `Bearer resource_metadata=\"${metadata}\", scope=\"${MCP_SCOPE}\"`,\n },\n },\n );\n },\n async delegate(host: HostPrincipal, turn: TurnDelegation): Promise<Delegation> {\n await ready();\n return delegate(await installed().turnKeys.keys(), host, turn, Date.now());\n },\n async hostActive(grantId: GrantId): Promise<boolean> {\n const revoked = await started().isRevoked({ kind: \"grant\", id: grantId });\n return !revoked && (await installed().grantKeys.get(grantId)) !== undefined;\n },\n async device(userId: UserId, deviceId: DeviceId): Promise<DeviceKeys | undefined> {\n const registered = await installed().devices.get(userId, deviceId);\n if (!registered) return undefined;\n const { id, name, platform, signingKey, presenceKey, vouches } = registered;\n return {\n id,\n name,\n platform,\n signingKey,\n presenceKey,\n ...(vouches ? { vouches } : {}),\n };\n },\n async account(userId: UserId): Promise<AccountProfile | undefined> {\n const { adapter } = await instance.$context;\n const user = await adapter.findOne<{ name: string; email: string }>({\n model: \"user\",\n where: [{ field: \"id\", value: userId }],\n });\n return user ? { name: user.name, email: user.email } : undefined;\n },\n revoked(principal: AuthenticatedPrincipal): AbortSignal {\n const notice =\n principal.kind === \"user\"\n ? ({ kind: \"session\", id: principal.sessionId } as const)\n : ({ kind: \"grant\", id: principal.grantId } as const);\n return started().signal([notice], authenticatedAt.get(principal));\n },\n };\n}\n"]}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AgentPrincipal,\n ANONYMOUS,\n asId,\n type AuthenticatedPrincipal,\n type DeviceId,\n type GrantId,\n type HostPrincipal,\n type Principal,\n type UserId,\n type UserPrincipal,\n} from \"@parlor/core\";\nimport { createRegistry } from \"@parlor/core/registry\";\nimport {\n type AccountProfile,\n AuthFailure,\n type AuthProvider,\n type Delegation,\n type DeviceKeys,\n type PluginHost,\n REVOCATION_HORIZON_MS,\n type TurnDelegation,\n type AgentDelegation,\n} from \"@parlor/server\";\nimport { betterAuth, type BetterAuthOptions } from \"better-auth\";\nimport {\n createLocalJWKSet,\n decodeProtectedHeader,\n errors,\n type JSONWebKeySet,\n type JWTPayload,\n jwtVerify,\n} from \"jose\";\n\nimport { accountActions } from \"./account.js\";\nimport { AUDIT_MIGRATION, createAuditLog } from \"./audit.js\";\nimport {\n AUTH_PLUGIN,\n bridgeOf,\n MCP_SCOPE,\n type ParlorAuthSettings,\n} from \"./better-auth.js\";\nimport {\n createDeviceRegistry,\n type DeviceRegistry,\n deviceAccountActions,\n DEVICE_LINKING_MIGRATION,\n DEVICES_MIGRATION,\n} from \"./devices.js\";\nimport { grantIdOf } from \"./grants.js\";\nimport {\n createGrantKeys,\n type GrantKeys,\n hostAccountActions,\n hostPrincipalOf,\n HOSTS_MIGRATION,\n hostRoutes,\n verifyHostAssertion,\n} from \"./hosts.js\";\nimport { AUTH_MIGRATIONS } from \"./migrations.js\";\nimport { RevocationSet } from \"./revocation.js\";\nimport { authRoutes } from \"./routes.js\";\nimport {\n type AgentToken,\n agentPrincipalOf,\n credentialOf,\n delegate,\n delegateAgent,\n type HostAssertion,\n outsideAgentPrincipalOf,\n type TurnToken,\n verifyAgentToken,\n verifyTurnToken,\n} from \"./tokens.js\";\nimport {\n createTurnKeyStore,\n TURN_KEYS_MIGRATION,\n type TurnKeyStore,\n} from \"./turn-keys.js\";\n\n/** The slice of a Better Auth instance Parlor relies on. */\nexport interface BetterAuthInstance {\n readonly options: BetterAuthOptions;\n handler(request: Request): Promise<Response>;\n readonly api: {\n getSession(input: { headers: Headers }): Promise<{\n readonly session: { readonly id: string; readonly userId: string };\n readonly user: {\n readonly id: string;\n readonly name: string;\n readonly email: string;\n };\n } | null>;\n };\n readonly $context: Promise<BetterAuthContext>;\n}\n\ninterface Where {\n readonly field: string;\n readonly value: string;\n}\n\nexport interface BetterAuthContext {\n readonly authCookies: { readonly sessionToken: { readonly name: string } };\n readonly adapter: {\n findMany<T>(input: { model: string; where?: Where[] }): Promise<T[]>;\n findOne<T>(input: { model: string; where: Where[] }): Promise<T | null>;\n deleteMany(input: { model: string; where: Where[] }): Promise<number>;\n };\n readonly secret: string;\n readonly internalAdapter: {\n listSessions(userId: string): Promise<StoredSession[]>;\n deleteSession(token: string): Promise<void>;\n };\n}\n\nexport interface StoredSession {\n readonly id: string;\n readonly token: string;\n readonly userId: string;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n readonly expiresAt: Date;\n readonly ipAddress?: string | null | undefined;\n readonly userAgent?: string | null | undefined;\n}\n\nexport type BetterAuthProviderOptions =\n | { readonly instance: BetterAuthInstance }\n | {\n /**\n * The options for `betterAuth()`, which the provider calls on the first request.\n * Better Auth starts querying the database as soon as it is created, and some\n * runtimes, such as Cloudflare's, allow no I/O while the app loads.\n */\n readonly options: BetterAuthOptions;\n };\n\n/** Stands in for the instance until the first call needs it. */\nfunction deferredInstance(options: BetterAuthOptions): BetterAuthInstance {\n let created: BetterAuthInstance | undefined;\n const current = () =>\n (created ??= betterAuth(options) as unknown as BetterAuthInstance);\n return {\n options,\n handler: (request) => current().handler(request),\n api: { getSession: (input) => current().api.getSession(input) },\n get $context() {\n return current().$context;\n },\n };\n}\n\nfunction hasCookie(request: Request, name: string): boolean {\n const cookie = request.headers.get(\"cookie\");\n if (!cookie) return false;\n return cookie.split(\";\").some((part) => part.trim().startsWith(`${name}=`));\n}\n\n/**\n * Sessions become user principals: a cookie on the same-origin web, a bearer token in\n * native shells. Access tokens Better Auth issued to MCP clients become agent principals\n * without a turn.\n */\nexport function betterAuthProvider(provided: BetterAuthProviderOptions): AuthProvider {\n const instance =\n \"instance\" in provided ? provided.instance : deferredInstance(provided.options);\n const bridge = bridgeOf(instance.options);\n const settings: ParlorAuthSettings = bridge.settings;\n let revocations: RevocationSet | undefined;\n let keys: ReturnType<typeof createLocalJWKSet> | undefined;\n let grantKeys: GrantKeys | undefined;\n let turnKeys: TurnKeyStore | undefined;\n let devices: DeviceRegistry | undefined;\n const clientNames = new Map<string, Promise<string>>();\n const authenticatedAt = new WeakMap<object, number>();\n\n const installed = () => {\n if (!grantKeys || !turnKeys || !devices) {\n throw new Error(\"The auth provider is not installed.\");\n }\n return { grantKeys, turnKeys, devices };\n };\n\n const started = () => {\n if (!revocations) throw new Error(\"The auth provider is not installed.\");\n return revocations;\n };\n\n let preparingTurnKeys = false;\n const ready = async (): Promise<void> => {\n await started().ready();\n if (!preparingTurnKeys) {\n preparingTurnKeys = true;\n installed()\n .turnKeys.keys()\n .catch(() => {\n preparingTurnKeys = false;\n });\n }\n };\n\n const loadKeys = async () => {\n const response = await instance.handler(new Request(`${settings.baseURL}/jwks`));\n if (!response.ok)\n throw new Error(`Better Auth answered /jwks with ${response.status}`);\n return createLocalJWKSet((await response.json()) as JSONWebKeySet);\n };\n\n const verify = async (token: string): Promise<JWTPayload> => {\n const options = {\n issuer: settings.baseURL,\n audience: settings.resource,\n typ: \"at+jwt\",\n };\n keys ??= await loadKeys();\n try {\n return (await jwtVerify(token, keys, options)).payload;\n } catch (error) {\n if (!(error instanceof errors.JWKSNoMatchingKey)) throw error;\n keys = await loadKeys();\n return (await jwtVerify(token, keys, options)).payload;\n }\n };\n\n const clientName = (clientId: string): Promise<string> => {\n let name = clientNames.get(clientId);\n if (!name) {\n name = instance.$context\n .then((context) =>\n context.adapter.findOne<{ name?: string | null }>({\n model: \"oauthClient\",\n where: [{ field: \"clientId\", value: clientId }],\n }),\n )\n .then((client) => client?.name || clientId);\n name.catch(() => clientNames.delete(clientId));\n clientNames.set(clientId, name);\n }\n return name;\n };\n\n const agentOf = async (token: string): Promise<AgentPrincipal> => {\n let payload: JWTPayload;\n try {\n payload = await verify(token);\n } catch (error) {\n if (error instanceof errors.JWTExpired) {\n throw new AuthFailure(\"expired\", \"The access token expired.\");\n }\n throw new AuthFailure(\"invalid\", \"The access token is invalid.\");\n }\n const { sub, iat } = payload;\n const clientId = payload.client_id;\n const scopes = typeof payload.scope === \"string\" ? payload.scope.split(\" \") : [];\n if (typeof sub !== \"string\" || typeof clientId !== \"string\" || iat === undefined) {\n throw new AuthFailure(\"invalid\", \"The access token is missing claims.\");\n }\n if (!scopes.includes(MCP_SCOPE)) {\n throw new AuthFailure(\n \"invalid\",\n `The access token lacks the \"${MCP_SCOPE}\" scope.`,\n );\n }\n const grantId = grantIdOf(sub, clientId);\n if (await started().isRevoked({ kind: \"grant\", id: grantId }, iat * 1000)) {\n throw new AuthFailure(\"revoked\", \"Access for this agent was revoked.\");\n }\n return {\n kind: \"agent\",\n userId: asId(\"user\", sub),\n grantId,\n agent: {\n name: await clientName(clientId),\n verified: clientId.startsWith(\"https://\"),\n },\n };\n };\n\n const userOf = async (request: Request): Promise<UserPrincipal | undefined> => {\n const found = await instance.api.getSession({ headers: request.headers });\n if (!found) return undefined;\n return {\n kind: \"user\",\n userId: asId(\"user\", found.user.id),\n sessionId: found.session.id,\n };\n };\n\n const publicUrlOf = (request: Request): string =>\n new URL(new URL(request.url).pathname, settings.origin).href;\n\n const hostOf = async (\n request: Request,\n assertion: HostAssertion,\n ): Promise<HostPrincipal> => {\n const grant = await verifyHostAssertion(\n assertion,\n { method: request.method, url: publicUrlOf(request) },\n installed().grantKeys,\n Date.now(),\n );\n if (await started().isRevoked({ kind: \"grant\", id: grant.grantId })) {\n throw new AuthFailure(\"revoked\", \"This computer was disconnected.\");\n }\n return hostPrincipalOf(grant);\n };\n\n const turnOf = async (token: TurnToken): Promise<AgentPrincipal> => {\n const store = installed().turnKeys;\n let turnTokenKeys = await store.keys();\n const kid = decodeProtectedHeader(token).kid;\n if (kid !== undefined && !turnTokenKeys.publicKeys.has(kid)) {\n turnTokenKeys = await store.refresh();\n }\n const claims = await verifyTurnToken(turnTokenKeys, token, Date.now());\n if (await started().isRevoked({ kind: \"grant\", id: claims.gid })) {\n throw new AuthFailure(\"revoked\", \"This computer was disconnected.\");\n }\n return agentPrincipalOf(claims);\n };\n\n const outsideAgentOf = async (token: AgentToken): Promise<AgentPrincipal> => {\n const store = installed().turnKeys;\n let turnTokenKeys = await store.keys();\n const kid = decodeProtectedHeader(token).kid;\n if (kid !== undefined && !turnTokenKeys.publicKeys.has(kid)) {\n turnTokenKeys = await store.refresh();\n }\n const claims = await verifyAgentToken(turnTokenKeys, token, Date.now());\n if (await started().isRevoked({ kind: \"grant\", id: claims.gid })) {\n throw new AuthFailure(\"revoked\", \"This computer was disconnected.\");\n }\n return outsideAgentPrincipalOf(claims);\n };\n\n const authenticateRequest = async (request: Request): Promise<Principal> => {\n await ready();\n const credential = credentialOf(request.headers.get(\"authorization\"));\n switch (credential?.kind) {\n case \"host\":\n return hostOf(request, credential.assertion);\n case \"turn\":\n return turnOf(credential.token);\n case \"agent\":\n return outsideAgentOf(credential.token);\n case \"access\":\n return agentOf(credential.token);\n case \"session\": {\n const user = await userOf(request);\n if (!user)\n throw new AuthFailure(\"invalid\", \"The session is invalid or has ended.\");\n return user;\n }\n case undefined:\n break;\n }\n const { authCookies } = await instance.$context;\n if (!hasCookie(request, authCookies.sessionToken.name)) return ANONYMOUS;\n return (await userOf(request)) ?? ANONYMOUS;\n };\n\n return {\n name: AUTH_PLUGIN,\n migrations: [\n ...AUTH_MIGRATIONS,\n HOSTS_MIGRATION,\n DEVICES_MIGRATION,\n TURN_KEYS_MIGRATION,\n AUDIT_MIGRATION,\n DEVICE_LINKING_MIGRATION,\n ],\n enforcing: true,\n setup(host: PluginHost) {\n const { database } = host;\n if (!database) throw new Error(\"The auth plugin needs a database.\");\n const set = new RevocationSet({\n database,\n horizonMs: REVOCATION_HORIZON_MS,\n });\n revocations = set;\n const auditLog = createAuditLog(database);\n bridge.revoke = (notice) =>\n database.transaction((tx) => RevocationSet.revoke(tx, notice));\n grantKeys = createGrantKeys(database);\n devices = createDeviceRegistry(database);\n turnKeys = createTurnKeyStore({\n database,\n issuer: settings.baseURL,\n secret: async () => (await instance.$context).secret,\n });\n const hostDeps = {\n host,\n settings,\n };\n return {\n actions: createRegistry({\n ...accountActions({ instance, host, revoke: bridge.revoke }).actions,\n ...hostAccountActions(hostDeps).actions,\n ...deviceAccountActions({ host, registry: devices }).actions,\n }),\n routes: [...authRoutes({ instance, settings, host }), ...hostRoutes(hostDeps)],\n audit: (record) => auditLog.record(record),\n close: async () => {\n await Promise.all([set.stop(), auditLog.stop()]);\n },\n };\n },\n async authenticate(request: Request): Promise<Principal> {\n const startedAt = Date.now();\n const principal = await authenticateRequest(request);\n if (principal.kind !== \"anonymous\") authenticatedAt.set(principal, startedAt);\n return principal;\n },\n challenge(): Response {\n const metadata = `${settings.origin}/.well-known/oauth-protected-resource${new URL(settings.resource).pathname}`;\n return Response.json(\n { error: { code: \"unauthenticated\", message: \"Sign in through OAuth first.\" } },\n {\n status: 401,\n headers: {\n \"www-authenticate\": `Bearer resource_metadata=\"${metadata}\", scope=\"${MCP_SCOPE}\"`,\n },\n },\n );\n },\n async delegate(host: HostPrincipal, turn: TurnDelegation): Promise<Delegation> {\n await ready();\n return delegate(await installed().turnKeys.keys(), host, turn, Date.now());\n },\n async delegateAgent(\n host: HostPrincipal,\n agent: AgentDelegation,\n ): Promise<Delegation> {\n await ready();\n return delegateAgent(await installed().turnKeys.keys(), host, agent, Date.now());\n },\n async hostActive(grantId: GrantId): Promise<boolean> {\n const revoked = await started().isRevoked({ kind: \"grant\", id: grantId });\n return !revoked && (await installed().grantKeys.get(grantId)) !== undefined;\n },\n async device(userId: UserId, deviceId: DeviceId): Promise<DeviceKeys | undefined> {\n const registered = await installed().devices.get(userId, deviceId);\n if (!registered) return undefined;\n const { id, name, platform, signingKey, presenceKey, vouches } = registered;\n return {\n id,\n name,\n platform,\n signingKey,\n presenceKey,\n ...(vouches ? { vouches } : {}),\n };\n },\n async account(userId: UserId): Promise<AccountProfile | undefined> {\n const { adapter } = await instance.$context;\n const user = await adapter.findOne<{ name: string; email: string }>({\n model: \"user\",\n where: [{ field: \"id\", value: userId }],\n });\n return user ? { name: user.name, email: user.email } : undefined;\n },\n revoked(principal: AuthenticatedPrincipal): AbortSignal {\n const notice =\n principal.kind === \"user\"\n ? ({ kind: \"session\", id: principal.sessionId } as const)\n : ({ kind: \"grant\", id: principal.grantId } as const);\n return started().signal([notice], authenticatedAt.get(principal));\n },\n };\n}\n"]}
@@ -82,6 +82,8 @@ export declare function vouchStatement(app: string, voucher: string, device: str
82
82
  export declare function removeStatement(app: string, actor: string, device: string, at: number): RemoveStatement;
83
83
  /** The fragment Parlor Host's loopback redirect carries back to the browser that approved `connect`. */
84
84
  export declare const HOST_PAIRING_FRAGMENT = "parlor-host-pairing";
85
+ /** Where a browser keeps that secret, for its first prompt to prove. */
86
+ export declare const HOST_PAIRING_KEY = "parlor:host-pairing";
85
87
  /**
86
88
  * The browser that approved `connect` gets the host's pairing secret through the loopback
87
89
  * redirect, never through the app; this binds it to one device's keys.
@@ -1 +1 @@
1
- {"version":3,"file":"statements.d.ts","sourceRoot":"","sources":["../src/statements.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"statements.d.ts","sourceRoot":"","sources":["../src/statements.ts"],"names":[],"mappings":"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"}
@@ -102,6 +102,8 @@ export function removeStatement(app, actor, device, at) {
102
102
  }
103
103
  /** The fragment Parlor Host's loopback redirect carries back to the browser that approved `connect`. */
104
104
  export const HOST_PAIRING_FRAGMENT = "parlor-host-pairing";
105
+ /** Where a browser keeps that secret, for its first prompt to prove. */
106
+ export const HOST_PAIRING_KEY = "parlor:host-pairing";
105
107
  const pairingKey = (secret) => crypto.subtle.importKey("raw", new Uint8Array(decodeBase64url(secret)), { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"]);
106
108
  const pairingBytes = (deviceId, signingKey) => canonicalBytes({
107
109
  v: 1,