fix: recover from expired enterprise auth on remote config load (#31661)
This commit is contained in:
parent
3ad6923c61
commit
02608a4e97
5 changed files with 67 additions and 7 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import { test, expect, describe, afterEach, beforeEach, spyOn } from "bun:test"
|
||||
import { ConfigV1 } from "@opencode-ai/core/v1/config/config"
|
||||
import { Effect, Exit, Layer, Option } from "effect"
|
||||
import { Cause, Effect, Exit, Layer, Option } from "effect"
|
||||
import { NamedError } from "@opencode-ai/core/util/error"
|
||||
import { FetchHttpClient, HttpClient, HttpClientResponse } from "effect/unstable/http"
|
||||
import { NodeFileSystem, NodePath } from "@effect/platform-node"
|
||||
import { Config } from "@/config/config"
|
||||
|
|
@ -71,6 +72,7 @@ const wellKnownAuth = (url: string) =>
|
|||
function remoteConfigClient(input: {
|
||||
wellKnown: unknown
|
||||
remote?: unknown
|
||||
remoteHtml?: string
|
||||
seen: { wellKnown?: string; remote?: string; authorization?: string }
|
||||
}) {
|
||||
return HttpClient.make((request) => {
|
||||
|
|
@ -78,9 +80,17 @@ function remoteConfigClient(input: {
|
|||
input.seen.wellKnown = request.url
|
||||
return Effect.succeed(json(request, input.wellKnown))
|
||||
}
|
||||
if (input.remote !== undefined && request.url.includes("config.example.com")) {
|
||||
if (request.url.includes("config.example.com") && (input.remote !== undefined || input.remoteHtml !== undefined)) {
|
||||
input.seen.remote = request.url
|
||||
input.seen.authorization = request.headers.authorization
|
||||
if (input.remoteHtml !== undefined) {
|
||||
return Effect.succeed(
|
||||
HttpClientResponse.fromWeb(
|
||||
request,
|
||||
new Response(input.remoteHtml, { status: 200, headers: { "content-type": "text/html; charset=utf-8" } }),
|
||||
),
|
||||
)
|
||||
}
|
||||
return Effect.succeed(json(request, input.remote))
|
||||
}
|
||||
return Effect.succeed(json(request, {}, 404))
|
||||
|
|
@ -214,6 +224,7 @@ const wellKnown = (input: {
|
|||
config?: unknown
|
||||
remoteConfig?: { url: string; headers?: Record<string, string> }
|
||||
remote?: unknown
|
||||
remoteHtml?: string
|
||||
wellKnown?: unknown
|
||||
}) => {
|
||||
const seen: { wellKnown?: string; remote?: string; authorization?: string } = {}
|
||||
|
|
@ -224,6 +235,7 @@ const wellKnown = (input: {
|
|||
...(input.remoteConfig !== undefined ? { remote_config: input.remoteConfig } : {}),
|
||||
},
|
||||
remote: input.remote,
|
||||
remoteHtml: input.remoteHtml,
|
||||
})
|
||||
return {
|
||||
seen,
|
||||
|
|
@ -1635,6 +1647,24 @@ invalidRemoteWellKnown.it.instance("wellknown remote_config rejects non-object c
|
|||
}),
|
||||
)
|
||||
|
||||
const loginPageWellKnown = wellKnown({
|
||||
remoteConfig: { url: "https://config.example.com/opencode.json" },
|
||||
remoteHtml: "<!DOCTYPE html><html><head><title>Sign in</title></head><body>Login required</body></html>",
|
||||
})
|
||||
|
||||
loginPageWellKnown.it.instance(
|
||||
"wellknown remote_config surfaces an actionable auth error when the gateway returns an HTML login page",
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const exit = yield* Config.use.get().pipe(Effect.exit)
|
||||
expect(loginPageWellKnown.seen.remote).toBe("https://config.example.com/opencode.json")
|
||||
expect(Exit.isFailure(exit)).toBe(true)
|
||||
const error = Exit.isFailure(exit) ? Cause.squash(exit.cause) : undefined
|
||||
expect(NamedError.hasName(error, "ConfigRemoteAuthError")).toBe(true)
|
||||
expect((error as { data?: { url?: string } }).data?.url).toBe("https://example.com")
|
||||
}),
|
||||
)
|
||||
|
||||
describe("resolvePluginSpec", () => {
|
||||
test("keeps package specs unchanged", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue