Something went wrong. Try again.
Something went wrong. Try again.
36 kB · 865 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866import { test, afterEach, beforeEach } from "node:test"import assert from "node:assert/strict"import fs from "node:fs"import os from "node:os"import path from "node:path"import Fastify from "fastify"import { registerAdminRoutes } from "./admin"import { isModelAllowed, loadApiKeys, type ApiKeyEntry } from "./auth"import { logout, providerStatus, resolveAnthropicAuthPath, registerProvider, stateDir } from "./oauth-login"import { readCodexCredential, writeCodexCredential } from "./codex-auth"import { readOAuthCredential, writeOAuthCredential } from "./anthropic-oauth"import type { BridgeConfig } from "./config"import { accountCredentialPath, createAccount } from "./accounts"import { recordTokenUsage } from "./token-usage"
const ADMIN_KEY = "11111111-2222-4333-8444-555555555555"const PLAIN_KEY = "99999999-8888-4777-8666-555555555555"
const tmpDirs: string[] = []const originalStateDir = process.env.BRIDGE_STATE_DIR
beforeEach(() => { process.env.BRIDGE_STATE_DIR = tmpDir()})
function tmpDir(): string { const dir = fs.mkdtempSync(path.join(os.tmpdir(), "bridge-admin-")) tmpDirs.push(dir) return dir}
afterEach(() => { for (const dir of tmpDirs.splice(0)) fs.rmSync(dir, { recursive: true, force: true }) if (originalStateDir === undefined) delete process.env.BRIDGE_STATE_DIR else process.env.BRIDGE_STATE_DIR = originalStateDir})
function keys(entries: Array<Partial<ApiKeyEntry> & { key: string }>): Map<string, ApiKeyEntry> { return new Map( entries.map((e) => [ e.key, { key: e.key, allowedModels: e.allowedModels ?? ["*"], caps: e.caps ?? [] } satisfies ApiKeyEntry, ]), )}
function makeApp(apiKeys: Map<string, ApiKeyEntry>, config?: Partial<BridgeConfig>) { const full: BridgeConfig = { port: 0, host: "127.0.0.1", providers: {}, models: {}, ...config, } const app = Fastify({ logger: false }) registerAdminRoutes(app, full, apiKeys, async () => {}) return { app, config: full }}
const bearer = (key: string) => ({ authorization: `Bearer ${key}` })
// ── capability gating ─────────────────────────────────────────────────────────// /admin is proxied to the public internet along with the rest of :4040, so// these are the only thing standing in front of the credential routes.
test("an unknown key is refused", async () => { const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }])) const res = await app.inject({ method: "GET", url: "/admin/api/providers", headers: bearer("00000000-0000-4000-8000-000000000000"), }) assert.equal(res.statusCode, 401)})
test("a missing key is refused", async () => { const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }])) assert.equal((await app.inject({ method: "GET", url: "/admin/api/providers" })).statusCode, 401)})
test("an open bridge exposes the admin API without frontend authentication", async () => { const { app } = makeApp(new Map()) const session = await app.inject({ method: "GET", url: "/admin/api/auth/session" }) assert.equal(session.statusCode, 200) assert.deepEqual(session.json(), { authenticated: true }) assert.equal((await app.inject({ method: "GET", url: "/admin/api/providers" })).statusCode, 200) assert.equal((await app.inject({ method: "GET", url: "/admin/api/accounts" })).statusCode, 200)})
test("admin cookie sessions validate capability, set safe flags, authenticate, and log out", async () => { const { app } = makeApp( keys([ { key: ADMIN_KEY, caps: ["admin"] }, { key: PLAIN_KEY, caps: ["reader"] }, ]), { models: { demo: { id: "demo", name: "Demo", provider: "test", apiKey: "secret" } } }, )
const invalid = await app.inject({ method: "POST", url: "/admin/api/auth/session", payload: { key: "not-a-key" } }) assert.equal(invalid.statusCode, 401) assert.equal(invalid.headers["set-cookie"], undefined) const forbidden = await app.inject({ method: "POST", url: "/admin/api/auth/session", payload: { key: PLAIN_KEY } }) assert.equal(forbidden.statusCode, 403) assert.equal(forbidden.headers["set-cookie"], undefined)
const login = await app.inject({ method: "POST", url: "/admin/api/auth/session", payload: { key: ADMIN_KEY } }) assert.equal(login.statusCode, 200) const setCookie = String(login.headers["set-cookie"]) assert.match(setCookie, /^llm_bridge_admin_session=[^;]+; Path=\/admin; HttpOnly; SameSite=Strict$/) assert.equal(setCookie.includes("Secure"), false) const cookie = setCookie.split(";", 1)[0]!
const listed = await app.inject({ method: "GET", url: "/admin/api/models", headers: { cookie } }) assert.equal(listed.statusCode, 200) assert.equal(listed.json().models[0].id, "demo")
const logout = await app.inject({ method: "DELETE", url: "/admin/api/auth/session", headers: { cookie } }) assert.equal(logout.statusCode, 204) assert.match( String(logout.headers["set-cookie"]), /^llm_bridge_admin_session=; Path=\/admin; HttpOnly; SameSite=Strict; Max-Age=0$/, ) assert.equal((await app.inject({ method: "GET", url: "/admin/api/models", headers: { cookie } })).statusCode, 401)
const secureLogin = await app.inject({ method: "POST", url: "/admin/api/auth/session", headers: { "x-forwarded-proto": "https" }, payload: { key: ADMIN_KEY }, }) assert.match(String(secureLogin.headers["set-cookie"]), /; Secure$/)})
test("programmatic admin callers can use x-api-key", async () => { const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }])) const response = await app.inject({ method: "GET", url: "/admin/api/models", headers: { "x-api-key": ADMIN_KEY } }) assert.equal(response.statusCode, 200)})
test("model wildcard does not grant admin access to sensitive routes", async () => { const { app } = makeApp(keys([{ key: PLAIN_KEY, allowedModels: ["*"], caps: ["reader"] }])) const routes: Array<[string, string]> = [ ["GET", "/admin/api/providers"], ["POST", "/admin/api/login/anthropic"], ["POST", "/admin/api/login/codex"], ["POST", "/admin/api/logout/anthropic"], ["GET", "/admin/api/session/whatever"], ["POST", "/admin/api/session/whatever/code"], ["DELETE", "/admin/api/session/whatever"], ["PATCH", "/admin/api/accounts/11111111-2222-4333-8444-555555555555"], ] for (const [method, url] of routes) { const res = await app.inject({ method: method as any, url, headers: bearer(PLAIN_KEY) }) assert.equal(res.statusCode, 403, `${method} ${url} should be gated`) }})
test("an admin key reaches the providers list", async () => { const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }])) const res = await app.inject({ method: "GET", url: "/admin/api/providers", headers: bearer(ADMIN_KEY) }) assert.equal(res.statusCode, 200) assert.deepEqual( res.json().providers.map((p: { id: string }) => p.id), ["anthropic", "codex", "antigravity", "opencode-go"], )})
test("models API exposes live catalog metadata without credentials", async () => { const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }]), { models: { "priced-model": { id: "priced-model", name: "Priced Model", provider: "custom", apiKey: "provider-secret", authPath: "/secret/auth.json", baseUrl: "https://internal.example.test", contextWindow: 128_000, maxTokens: 16_000, reasoning: true, cost: { input: 1.25, output: 5, cacheRead: 0.25, cacheWrite: 1.5 }, }, unknowns: { id: "unknowns", name: "Unknown limits", provider: "custom", apiKey: "another-secret" }, }, }) recordTokenUsage(stateDir(), { apiKey: ADMIN_KEY, provider: "codex", model: "priced-model", inputTokens: 750_000, outputTokens: 250_000, totalTokens: 1_000_000, planPrimaryDelta: 0.4, }) const unauthorized = await app.inject({ method: "GET", url: "/admin/api/models", headers: bearer(PLAIN_KEY) }) assert.equal(unauthorized.statusCode, 401)
const response = await app.inject({ method: "GET", url: "/admin/api/models", headers: bearer(ADMIN_KEY) }) assert.equal(response.statusCode, 200) assert.deepEqual(response.json(), { models: [ { id: "priced-model", name: "Priced Model", provider: "custom", contextWindow: 128_000, maxTokens: 16_000, reasoning: true, cost: { input: 1.25, output: 5, cacheRead: 0.25, cacheWrite: 1.5 }, observedUsage: { requests: 1, totalTokens: 1_000_000, planPercentDelta: 0.4, percentPer1MTokens: 0.4 }, }, { id: "unknowns", name: "Unknown limits", provider: "custom" }, ], }) assert.equal(response.body.includes("provider-secret"), false) assert.equal(response.body.includes("auth.json"), false)})
test("settings API updates the Fast-mode price ceiling and refreshes models", async () => { let refreshes = 0 const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: {}, models: {}, codexFastMaxOutputCostPerMTok: 20, } const app = Fastify({ logger: false }) registerAdminRoutes(app, config, keys([{ key: ADMIN_KEY, caps: ["admin"] }]), async () => { refreshes++ })
const initial = await app.inject({ method: "GET", url: "/admin/api/settings", headers: bearer(ADMIN_KEY) }) assert.deepEqual(initial.json(), { codexFastMaxOutputCostPerMTok: 20 })
const saved = await app.inject({ method: "PUT", url: "/admin/api/settings", headers: bearer(ADMIN_KEY), payload: { codexFastMaxOutputCostPerMTok: 27.5 }, }) assert.equal(saved.statusCode, 200) assert.deepEqual(saved.json(), { codexFastMaxOutputCostPerMTok: 27.5 }) assert.equal(config.codexFastMaxOutputCostPerMTok, 27.5) assert.equal(refreshes, 1)
const invalid = await app.inject({ method: "PUT", url: "/admin/api/settings", headers: bearer(ADMIN_KEY), payload: { codexFastMaxOutputCostPerMTok: -1 }, }) assert.equal(invalid.statusCode, 400) assert.equal(refreshes, 1)
const retired = await app.inject({ method: "PUT", url: "/admin/api/settings", headers: bearer(ADMIN_KEY), payload: { traceRetentionDays: 5 }, }) assert.equal(retired.statusCode, 400) assert.equal(retired.json().error.type, "invalid_request_error") assert.equal(refreshes, 1)})
test("account names can be created and updated", async () => { const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }])) const created = await app.inject({ method: "POST", url: "/admin/api/accounts", headers: bearer(ADMIN_KEY), payload: { provider: "anthropic", label: "work Claude" }, }) const createdBody: unknown = JSON.parse(created.body) if (!createdBody || typeof createdBody !== "object" || Array.isArray(createdBody) || !("account" in createdBody)) throw new Error("missing created account") const account = createdBody.account if ( !account || typeof account !== "object" || Array.isArray(account) || !("id" in account) || typeof account.id !== "string" ) throw new Error("missing created account ID") const accountId = account.id
const renamed = await app.inject({ method: "PATCH", url: `/admin/api/accounts/${accountId}`, headers: bearer(ADMIN_KEY), payload: { label: "personal Claude" }, }) assert.equal(renamed.statusCode, 200) assert.match(renamed.body, /personal Claude/)
const invalid = await app.inject({ method: "PATCH", url: `/admin/api/accounts/${accountId}`, headers: bearer(ADMIN_KEY), payload: { label: " " }, }) assert.equal(invalid.statusCode, 400)})
test("routing API stores exact pools and account usage is isolated", async () => { const previousFetch = globalThis.fetch const first = createAccount(stateDir(), "anthropic", "A") const second = createAccount(stateDir(), "anthropic", "B") writeOAuthCredential(accountCredentialPath(stateDir(), first.id, "anthropic")!, { type: "oauth", refresh: "r", access: "a-token", expires: Date.now() + 3_600_000, }) const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }]), { providers: { anthropic: {} } }) globalThis.fetch = (async (_input: string | URL | Request, init?: RequestInit) => { const token = new Headers(init?.headers).get("authorization") if (token?.includes("a-token")) return new Response( JSON.stringify({ five_hour: { utilization: 42, resets_at: new Date(Date.now() + 3_600_000).toISOString() }, seven_day: { utilization: 8 }, }), { status: 200 }, ) return new Response("", { status: 500 }) }) as typeof fetch try { const initial = (await app.inject({ method: "GET", url: "/admin/api/keys", headers: bearer(ADMIN_KEY) })).json() const id = initial.keys[0].id assert.equal(Object.hasOwn(initial.keys[0], "compaction"), false) const saved = await app.inject({ method: "PUT", url: `/admin/api/keys/${id}/routing`, headers: bearer(ADMIN_KEY), payload: { usageScheme: "specific-plan-first", accounts: { anthropic: [first.id, second.id] }, preferredAccounts: { anthropic: second.id }, }, }) assert.equal(saved.statusCode, 200) assert.deepEqual(saved.json().key.accounts, { anthropic: [first.id, second.id] }) assert.equal(saved.json().key.preferredAccounts.anthropic, second.id) assert.equal(saved.json().key.usageScheme, "specific-plan-first") assert.equal(Object.hasOwn(saved.json().key, "compaction"), false) const retired = await app.inject({ method: "PUT", url: `/admin/api/keys/${id}/routing`, headers: bearer(ADMIN_KEY), payload: { usageScheme: "specific-plan-first", accounts: { anthropic: [first.id, second.id] }, preferredAccounts: { anthropic: second.id }, compaction: { enabled: false }, }, }) assert.equal(retired.statusCode, 400) assert.equal(retired.json().error.type, "invalid_request_error") for (const payload of [ { usageScheme: "bad", accounts: {}, preferredAccounts: {} }, { usageScheme: "fill-first", accounts: { anthropic: [first.id] }, preferredAccounts: { anthropic: second.id } }, { usageScheme: "fill-first", accounts: { anthropic: [first.id, first.id] }, preferredAccounts: {} }, { usageScheme: "fill-first", accounts: { codex: [first.id] }, preferredAccounts: {} }, ]) { const invalid = await app.inject({ method: "PUT", url: `/admin/api/keys/${id}/routing`, headers: bearer(ADMIN_KEY), payload, }) assert.equal(invalid.statusCode, 400) assert.equal(invalid.json().error.type, "invalid_request_error") } const listed = await app.inject({ method: "GET", url: "/admin/api/accounts", headers: bearer(ADMIN_KEY) }) assert.equal(listed.statusCode, 200) const accounts = listed.json().accounts as Array<{ id: string history?: unknown[] status: { usage?: { available: boolean; usage?: { display?: string } } } }> assert.equal(accounts.find((account) => account.id === first.id)?.status.usage?.usage?.display, "5h 42% 7d 8%") assert.equal(accounts.find((account) => account.id === first.id)?.history?.length, 30) assert.deepEqual(accounts.find((account) => account.id === second.id)?.status.usage, { available: false, reason: "not-connected", }) assert.equal(JSON.stringify(listed.json()).includes("a-token"), false) } finally { await app.close() globalThis.fetch = previousFetch }})
test("Antigravity login starts a manual authorization flow", async () => { const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }])) const res = await app.inject({ method: "POST", url: "/admin/api/login/antigravity", headers: bearer(ADMIN_KEY) }) assert.equal(res.statusCode, 200) assert.equal(res.json().provider, "antigravity") assert.equal(res.json().kind, "paste") assert.match(res.json().authUrl, /^https:\/\/accounts\.google\.com\//)})
// ── keys file ─────────────────────────────────────────────────────────────────
test("caps default to none and parse when present", () => { const dir = tmpDir() const file = path.join(dir, "keys.json") fs.writeFileSync( file, JSON.stringify([ { key: ADMIN_KEY, allowedModels: ["*"], caps: ["admin"] }, { key: PLAIN_KEY, allowedModels: ["*"] }, ]), ) const loaded = loadApiKeys(file) assert.deepEqual(loaded.get(ADMIN_KEY)?.caps, ["admin"]) assert.deepEqual(loaded.get(PLAIN_KEY)?.caps, [])})
test("an explicitly empty allowedModels array is accepted without capabilities", () => { const dir = tmpDir() const file = path.join(dir, "keys.json") fs.writeFileSync(file, JSON.stringify([{ key: PLAIN_KEY, allowedModels: [] }]))
const loaded = loadApiKeys(file) const plainKey = loaded.get(PLAIN_KEY) assert.ok(plainKey) assert.deepEqual(plainKey.allowedModels, []) assert.deepEqual(plainKey.caps, []) assert.equal(isModelAllowed(plainKey, "claude-3-7-sonnet"), false)})
test("allowedModels is required and must be an array", () => { for (const entry of [{ key: ADMIN_KEY }, { key: ADMIN_KEY, allowedModels: "*" }]) { const dir = tmpDir() const file = path.join(dir, "keys.json") fs.writeFileSync(file, JSON.stringify([entry])) assert.throws(() => loadApiKeys(file), /allowedModels.*array/) }})
test("a malformed caps field fails loudly instead of silently dropping admin", () => { const dir = tmpDir() const file = path.join(dir, "keys.json") fs.writeFileSync(file, JSON.stringify([{ key: ADMIN_KEY, allowedModels: ["*"], caps: "admin" }])) assert.throws(() => loadApiKeys(file), /caps/)})
// ── credential round-trips ────────────────────────────────────────────────────
test("codex credentials are written in the CLI's shape, not pi-ai's", () => { // codex.ts and the real `codex` CLI both read auth.tokens.*; pi-ai's login // returns { access, refresh }. Persisting the wrong shape yields a login that // appears to succeed and then can't serve a single request. const authPath = path.join(tmpDir(), "auth.json") writeCodexCredential(authPath, { access: "access-tok", refresh: "refresh-tok", expires: 0 })
const raw = JSON.parse(fs.readFileSync(authPath, "utf-8")) assert.equal(raw.tokens.access_token, "access-tok") assert.equal(raw.tokens.refresh_token, "refresh-tok") assert.ok(raw.last_refresh) assert.equal(fs.statSync(authPath).mode & 0o777, 0o600)})
test("writing a codex credential preserves unrelated keys in the file", () => { const authPath = path.join(tmpDir(), "auth.json") fs.writeFileSync(authPath, JSON.stringify({ OPENAI_API_KEY: "sk-keep-me", tokens: { id_token: "id" } })) writeCodexCredential(authPath, { access: "a", refresh: "r", expires: 0 })
const raw = JSON.parse(fs.readFileSync(authPath, "utf-8")) assert.equal(raw.OPENAI_API_KEY, "sk-keep-me") assert.equal(raw.tokens.id_token, "id") assert.equal(raw.tokens.access_token, "a")})
test("a codex credential with no access token reads as absent", () => { const authPath = path.join(tmpDir(), "auth.json") assert.equal(readCodexCredential(authPath), null) fs.writeFileSync(authPath, JSON.stringify({ tokens: { refresh_token: "r" } })) assert.equal(readCodexCredential(authPath), null)})
test("anthropic credentials merge into a shared auth.json", () => { // The default path is ours, but pointing auth_path at a shared ~/.pi/auth.json // is supported and must not blow away another provider's entry. const authPath = path.join(tmpDir(), "auth.json") fs.writeFileSync(authPath, JSON.stringify({ openai: { type: "oauth", refresh: "keep", access: "x", expires: 1 } })) writeOAuthCredential(authPath, { type: "oauth", refresh: "r", access: "a", expires: 42 })
const raw = JSON.parse(fs.readFileSync(authPath, "utf-8")) assert.equal(raw.openai.refresh, "keep") assert.equal(raw.anthropic.access, "a") assert.equal(readOAuthCredential(authPath)?.expires, 42) assert.equal(fs.statSync(authPath).mode & 0o777, 0o600)})
// ── path resolution ───────────────────────────────────────────────────────────
test("codex's auth_path is never mistaken for the anthropic credential", () => { // Both providers carry an auth_path holding different shapes; scanning for // "any provider with an auth_path" would hand back codex's file. const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: { codex: { auth_path: "/tmp/codex-auth.json" } }, models: {}, } assert.notEqual(resolveAnthropicAuthPath(config), "/tmp/codex-auth.json") assert.equal(resolveAnthropicAuthPath(config), path.join(stateDir(), "auth", "anthropic.json"))})
test("an explicit anthropic auth_path wins over the state dir", () => { const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: { "anthropic-oauth": { auth_path: "/home/me/.pi/auth.json" } }, models: {}, } assert.equal(resolveAnthropicAuthPath(config), "/home/me/.pi/auth.json")})
test("a login registers a provider the config never mentioned", () => { // discoverModels only walks config.providers, so without this the token is // written correctly and then never read. const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: {}, models: {} } registerProvider(config, "anthropic", "/state/auth/anthropic.json") assert.equal(config.providers["anthropic-oauth"]?.auth_path, "/state/auth/anthropic.json")
registerProvider(config, "codex", "/state/auth/codex.json") assert.equal(config.providers["codex"]?.auth_path, "/state/auth/codex.json")})
test("registering never overwrites an operator-configured auth_path", () => { const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: { codex: { auth_path: "/run/configured/codex.json" } }, models: {}, } registerProvider(config, "codex", "/state/auth/codex.json") assert.equal(config.providers["codex"]?.auth_path, "/run/configured/codex.json")})
// ── concurrent logins ─────────────────────────────────────────────────────────
test("starting a second anthropic login supersedes the first", async () => { // A newer attempt must retire the pending prompt, not leave a stale session // that can still accept a pasted code. const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }]))
const first = await app.inject({ method: "POST", url: "/admin/api/login/anthropic", headers: bearer(ADMIN_KEY) }) assert.equal(first.statusCode, 200)
const second = await app.inject({ method: "POST", url: "/admin/api/login/anthropic", headers: bearer(ADMIN_KEY) }) assert.equal(second.statusCode, 200) assert.notEqual(second.json().id, first.json().id)
// The superseded session is gone, not lingering as a live flow. const stale = await app.inject({ method: "GET", url: `/admin/api/session/${first.json().id}`, headers: bearer(ADMIN_KEY), }) assert.equal(stale.statusCode, 404) const staleCode = await app.inject({ method: "POST", url: `/admin/api/session/${first.json().id}/code`, headers: bearer(ADMIN_KEY), payload: { code: "stale-code" }, }) assert.equal(staleCode.statusCode, 404)
await app.inject({ method: "DELETE", url: `/admin/api/session/${second.json().id}`, headers: bearer(ADMIN_KEY), })})
test("a mismatched OAuth state errors without network and refuses another pasted code", async () => { const previousFetch = globalThis.fetch let requests = 0 globalThis.fetch = (async () => { requests++ throw new Error("unexpected OAuth network request") }) as typeof fetch const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }])) let id: string | undefined try { const started = await app.inject({ method: "POST", url: "/admin/api/login/anthropic", headers: bearer(ADMIN_KEY) }) assert.equal(started.statusCode, 200) id = started.json().id const state = new URL(started.json().authUrl).searchParams.get("state") assert.ok(state) const send = () => app.inject({ method: "POST", url: `/admin/api/session/${id}/code`, headers: bearer(ADMIN_KEY), payload: { code: `abc#${state}-mismatch` }, })
assert.equal((await send()).statusCode, 200) assert.equal((await send()).statusCode, 409) await new Promise<void>((resolve) => setImmediate(resolve)) const session = await app.inject({ method: "GET", url: `/admin/api/session/${id}`, headers: bearer(ADMIN_KEY), }) assert.equal(session.json().status, "error") assert.match(session.json().error, /state/i) assert.equal(requests, 0) assert.equal(readOAuthCredential(accountCredentialPath(stateDir(), started.json().accountId, "anthropic")!), null) } finally { if (id) await app.inject({ method: "DELETE", url: `/admin/api/session/${id}`, headers: bearer(ADMIN_KEY) }) await app.close() globalThis.fetch = previousFetch }})
test("cancelling a pending Anthropic login allows a successful manual retry", { timeout: 5_000 }, async () => { const previousFetch = globalThis.fetch const account = createAccount(stateDir(), "anthropic", "work Claude") const authPath = accountCredentialPath(stateDir(), account.id, "anthropic")! const { app, config } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }])) const pending = new Set<string>() globalThis.fetch = (async (input: string | URL | Request) => { const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url assert.equal(url, "https://api.anthropic.com/v1/oauth/token") return new Response( JSON.stringify({ access_token: "manual-access", refresh_token: "manual-refresh", expires_in: 3600, account: { uuid: "claude-account", email_address: "work@example.com" }, organization: { uuid: "claude-org", name: "Work" }, }), { status: 200, headers: { "content-type": "application/json" } }, ) }) as typeof fetch try { const start = () => app.inject({ method: "POST", url: "/admin/api/login/anthropic", headers: bearer(ADMIN_KEY), payload: { accountId: account.id }, }) const first = await start() assert.equal(first.statusCode, 200) pending.add(first.json().id) assert.equal(first.json().status, "awaiting_code") const cancelled = await app.inject({ method: "DELETE", url: `/admin/api/session/${first.json().id}`, headers: bearer(ADMIN_KEY), }) assert.equal(cancelled.statusCode, 204) pending.delete(first.json().id) assert.equal( (await app.inject({ method: "GET", url: `/admin/api/session/${first.json().id}`, headers: bearer(ADMIN_KEY) })) .statusCode, 404, ) assert.equal( ( await app.inject({ method: "POST", url: `/admin/api/session/${first.json().id}/code`, headers: bearer(ADMIN_KEY), payload: { code: "cancelled-code" }, }) ).statusCode, 404, )
const retried = await start() assert.equal(retried.statusCode, 200) const id = retried.json().id pending.add(id) assert.notEqual(id, first.json().id) const before = Date.now() const submitted = await app.inject({ method: "POST", url: `/admin/api/session/${id}/code`, headers: bearer(ADMIN_KEY), payload: { code: "manual-code" }, }) assert.equal(submitted.statusCode, 200) assert.equal(submitted.json().status, "polling") await new Promise<void>((resolve) => setImmediate(resolve)) const completed = await app.inject({ method: "GET", url: `/admin/api/session/${id}`, headers: bearer(ADMIN_KEY) }) assert.equal(completed.json().status, "complete") assert.equal(completed.json().accountId, account.id)
const stored = JSON.parse(fs.readFileSync(authPath, "utf8")).anthropic assert.equal(stored.type, "oauth") assert.equal(stored.access, "manual-access") assert.equal(stored.refresh, "manual-refresh") assert.equal(stored.accountId, "claude-account") assert.equal(stored.email, "work@example.com") assert.equal(stored.orgId, "claude-org") assert.equal(stored.orgName, "Work") assert.equal(typeof stored.authorizedAt, "number") assert.ok(stored.authorizedAt >= before && stored.authorizedAt <= Date.now()) assert.equal(providerStatus(config, "anthropic", account.id).connected, true) } finally { for (const id of pending) { await app.inject({ method: "DELETE", url: `/admin/api/session/${id}`, headers: bearer(ADMIN_KEY) }) } await app.close() globalThis.fetch = previousFetch }})
test("an empty pasted code is refused", async () => { const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }])) const started = await app.inject({ method: "POST", url: "/admin/api/login/anthropic", headers: bearer(ADMIN_KEY) }) const res = await app.inject({ method: "POST", url: `/admin/api/session/${started.json().id}/code`, headers: bearer(ADMIN_KEY), payload: { code: " " }, }) assert.equal(res.statusCode, 400)
await app.inject({ method: "DELETE", url: `/admin/api/session/${started.json().id}`, headers: bearer(ADMIN_KEY), })})
test("a login session never exposes its resolvers", async () => { const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }])) const started = await app.inject({ method: "POST", url: "/admin/api/login/anthropic", headers: bearer(ADMIN_KEY) }) const body = started.json() for (const leak of ["submitCode", "failCode", "abort", "settled"]) { assert.ok(!(leak in body), `${leak} must not be serialised to the client`) }
await app.inject({ method: "DELETE", url: `/admin/api/session/${body.id}`, headers: bearer(ADMIN_KEY) })})
// ── status ────────────────────────────────────────────────────────────────────
test("status reports connected once a credential lands", () => { const dir = tmpDir() const authPath = path.join(dir, "codex.json") const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: { codex: { auth_path: authPath } }, models: {}, } assert.equal(providerStatus(config, "codex").connected, false)
writeCodexCredential(authPath, { access: "a", refresh: "r", expires: 0 }) assert.equal(providerStatus(config, "codex").connected, true)})
// ── sign-out ──────────────────────────────────────────────────────────────────
test("signing out of anthropic actually reads back as signed out", () => { // Blanking the fields instead of removing the entry left status reporting // connected with an empty refresh token, so every later request would attempt // a refresh and fail. const authPath = path.join(tmpDir(), "anthropic.json") const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: { "anthropic-oauth": { auth_path: authPath } }, models: {}, } writeOAuthCredential(authPath, { type: "oauth", refresh: "r", access: "a", expires: Date.now() + 3.6e6 }) assert.equal(providerStatus(config, "anthropic").connected, true)
logout(config, "anthropic") assert.equal(providerStatus(config, "anthropic").connected, false) assert.equal(readOAuthCredential(authPath), null)})
test("signing out leaves other providers in a shared auth.json alone", () => { const authPath = path.join(tmpDir(), "auth.json") fs.writeFileSync( authPath, JSON.stringify({ "github-copilot": { type: "oauth", refresh: "keep", access: "k", expires: 1 } }), ) writeOAuthCredential(authPath, { type: "oauth", refresh: "r", access: "a", expires: 1 })
const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: { "anthropic-oauth": { auth_path: authPath } }, models: {}, } logout(config, "anthropic")
const raw = JSON.parse(fs.readFileSync(authPath, "utf-8")) assert.equal(raw["github-copilot"].refresh, "keep") assert.ok(!("anthropic" in raw))})
test("signing out of codex clears the tokens but keeps unrelated keys", () => { const authPath = path.join(tmpDir(), "codex.json") fs.writeFileSync(authPath, JSON.stringify({ OPENAI_API_KEY: "sk-keep-me" })) writeCodexCredential(authPath, { access: "a", refresh: "r", expires: 0 })
const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: { codex: { auth_path: authPath } }, models: {} } assert.equal(providerStatus(config, "codex").connected, true)
logout(config, "codex") assert.equal(providerStatus(config, "codex").connected, false) assert.equal(JSON.parse(fs.readFileSync(authPath, "utf-8")).OPENAI_API_KEY, "sk-keep-me")})
test("an empty refresh token reads as absent, however it got there", () => { // Defensive half: a hand-edited or half-written file must not look valid. const authPath = path.join(tmpDir(), "anthropic.json") fs.writeFileSync(authPath, JSON.stringify({ anthropic: { type: "oauth", refresh: "", access: "", expires: 0 } })) assert.equal(readOAuthCredential(authPath), null)})
test("signing out of a provider that was never signed in is a no-op", () => { const authPath = path.join(tmpDir(), "anthropic.json") const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: { "anthropic-oauth": { auth_path: authPath } }, models: {}, } assert.doesNotThrow(() => logout(config, "anthropic")) assert.equal(fs.existsSync(authPath), false)})
test("a corrupt credential file reports an error rather than a clean 'not connected'", () => { const dir = tmpDir() const authPath = path.join(dir, "codex.json") fs.writeFileSync(authPath, "{ not json") const config: BridgeConfig = { port: 0, host: "127.0.0.1", providers: { codex: { auth_path: authPath } }, models: {}, } const status = providerStatus(config, "codex") assert.equal(status.connected, false) assert.ok(status.error, "a broken file must be distinguishable from a fresh install")})
test("request metrics dataset requires admin and paginates", async () => { const { app } = makeApp(keys([{ key: ADMIN_KEY, caps: ["admin"] }, { key: PLAIN_KEY }])) const url = `/admin/api/request-metrics?limit=2&offset=0` assert.equal((await app.inject({ url })).statusCode, 401) assert.equal((await app.inject({ url, headers: bearer(PLAIN_KEY) })).statusCode, 403) const response = await app.inject({ url, headers: bearer(ADMIN_KEY) }) assert.equal(response.statusCode, 200) assert.deepEqual(response.json(), { records: [], total: 0, limit: 2, offset: 0, hasMore: false }) assert.equal((await app.inject({ url: "/admin/api/compaction-events", headers: bearer(ADMIN_KEY) })).statusCode, 404) await app.close()})