fix(auth): opencode desktop server unauthorized bugfix on subagent spawn (#1399)
* fix(auth): opencode desktop server unauthorized bugfix on subagent spawn * refactor(auth): add runtime guard and throw on SDK mismatch - Add JSDoc with SDK API documentation reference - Replace silent failure with explicit Error throw when OPENCODE_SERVER_PASSWORD is set but client structure is incompatible - Add runtime type guard for SDK client structure - Add tests for error cases (missing _client, missing setConfig) - Remove unrelated bun.lock changes Co-authored-by: dan-myles <dan-myles@users.noreply.github.com> --------- Co-authored-by: YeonGyu-Kim <code.yeon.gyu@gmail.com> Co-authored-by: dan-myles <dan-myles@users.noreply.github.com>
This commit is contained in:
95
src/shared/opencode-server-auth.test.ts
Normal file
95
src/shared/opencode-server-auth.test.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { getServerBasicAuthHeader, injectServerAuthIntoClient } from "./opencode-server-auth"
|
||||
|
||||
describe("opencode-server-auth", () => {
|
||||
let originalEnv: Record<string, string | undefined>
|
||||
|
||||
beforeEach(() => {
|
||||
originalEnv = {
|
||||
OPENCODE_SERVER_PASSWORD: process.env.OPENCODE_SERVER_PASSWORD,
|
||||
OPENCODE_SERVER_USERNAME: process.env.OPENCODE_SERVER_USERNAME,
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
for (const [key, value] of Object.entries(originalEnv)) {
|
||||
if (value !== undefined) {
|
||||
process.env[key] = value
|
||||
} else {
|
||||
delete process.env[key]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test("#given no server password #when building auth header #then returns undefined", () => {
|
||||
delete process.env.OPENCODE_SERVER_PASSWORD
|
||||
|
||||
const result = getServerBasicAuthHeader()
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
|
||||
test("#given server password without username #when building auth header #then uses default username", () => {
|
||||
process.env.OPENCODE_SERVER_PASSWORD = "secret"
|
||||
delete process.env.OPENCODE_SERVER_USERNAME
|
||||
|
||||
const result = getServerBasicAuthHeader()
|
||||
|
||||
expect(result).toBe("Basic b3BlbmNvZGU6c2VjcmV0")
|
||||
})
|
||||
|
||||
test("#given server password and username #when building auth header #then uses provided username", () => {
|
||||
process.env.OPENCODE_SERVER_PASSWORD = "secret"
|
||||
process.env.OPENCODE_SERVER_USERNAME = "dan"
|
||||
|
||||
const result = getServerBasicAuthHeader()
|
||||
|
||||
expect(result).toBe("Basic ZGFuOnNlY3JldA==")
|
||||
})
|
||||
|
||||
test("#given server password #when injecting into client #then updates client headers", () => {
|
||||
process.env.OPENCODE_SERVER_PASSWORD = "secret"
|
||||
delete process.env.OPENCODE_SERVER_USERNAME
|
||||
|
||||
let receivedConfig: { headers: Record<string, string> } | undefined
|
||||
const client = {
|
||||
_client: {
|
||||
setConfig: (config: { headers: Record<string, string> }) => {
|
||||
receivedConfig = config
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
injectServerAuthIntoClient(client)
|
||||
|
||||
expect(receivedConfig).toEqual({
|
||||
headers: {
|
||||
Authorization: "Basic b3BlbmNvZGU6c2VjcmV0",
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("#given server password #when client has no _client #then throws error", () => {
|
||||
process.env.OPENCODE_SERVER_PASSWORD = "secret"
|
||||
const client = {}
|
||||
|
||||
expect(() => injectServerAuthIntoClient(client)).toThrow(
|
||||
"[opencode-server-auth] OPENCODE_SERVER_PASSWORD is set but SDK client structure is incompatible"
|
||||
)
|
||||
})
|
||||
|
||||
test("#given server password #when client._client has no setConfig #then throws error", () => {
|
||||
process.env.OPENCODE_SERVER_PASSWORD = "secret"
|
||||
const client = { _client: {} }
|
||||
|
||||
expect(() => injectServerAuthIntoClient(client)).toThrow(
|
||||
"[opencode-server-auth] OPENCODE_SERVER_PASSWORD is set but SDK client._client.setConfig is not a function"
|
||||
)
|
||||
})
|
||||
|
||||
test("#given no server password #when client is invalid #then does not throw", () => {
|
||||
delete process.env.OPENCODE_SERVER_PASSWORD
|
||||
const client = {}
|
||||
|
||||
expect(() => injectServerAuthIntoClient(client)).not.toThrow()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user