feat(core): add connector authentication (#31837)

This commit is contained in:
Dax 2026-06-11 02:31:17 -04:00 committed by GitHub
commit dac0dd5309
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
47 changed files with 5433 additions and 862 deletions

View file

@ -650,6 +650,49 @@ const scenarios: Scenario[] = [
http.protected.get("/api/agent", "v2.agent.list").json(200, locationData(array)),
http.protected.get("/api/model", "v2.model.list").json(200, locationData(array)),
http.protected.get("/api/provider", "v2.provider.list").json(200, locationData(array)),
http.protected.get("/api/connector", "v2.connector.list").json(200, locationData(array)),
http.protected
.get("/api/connector/{connectorID}", "v2.connector.get")
.at((ctx) => ({ path: route("/api/connector/{connectorID}", { connectorID: "missing" }), headers: ctx.headers() }))
.json(200, object),
http.protected
.post("/api/connector/{connectorID}/connect/key", "v2.connector.connect.key")
.at((ctx) => ({
path: route("/api/connector/{connectorID}/connect/key", { connectorID: "missing" }),
headers: ctx.headers(),
body: { methodID: "missing", key: "test", inputs: {} },
}))
.status(500, undefined, "status"),
http.protected
.post("/api/connector/{connectorID}/connect/oauth", "v2.connector.connect.oauth.begin")
.at((ctx) => ({
path: route("/api/connector/{connectorID}/connect/oauth", { connectorID: "missing" }),
headers: ctx.headers(),
body: { methodID: "missing", inputs: {} },
}))
.status(500, undefined, "status"),
http.protected
.get("/api/connector/oauth/{attemptID}", "v2.connector.connect.oauth.status")
.at((ctx) => ({
path: route("/api/connector/oauth/{attemptID}", { attemptID: "con_missing" }),
headers: ctx.headers(),
}))
.status(500, undefined, "status"),
http.protected
.post("/api/connector/oauth/{attemptID}/complete", "v2.connector.connect.oauth.complete")
.at((ctx) => ({
path: route("/api/connector/oauth/{attemptID}/complete", { attemptID: "con_missing" }),
headers: ctx.headers(),
body: {},
}))
.status(500, undefined, "status"),
http.protected
.delete("/api/connector/oauth/{attemptID}", "v2.connector.connect.oauth.cancel")
.at((ctx) => ({
path: route("/api/connector/oauth/{attemptID}", { attemptID: "con_missing" }),
headers: ctx.headers(),
}))
.status(204, undefined, "status"),
http.protected.get("/api/command", "v2.command.list").json(200, locationData(array)),
http.protected.get("/api/skill", "v2.skill.list").json(200, locationData(array)),
http.protected

View file

@ -115,6 +115,30 @@ describe("PublicApi OpenAPI v2 errors", () => {
}
})
test("documents connector discovery and connection routes", () => {
const spec = OpenApi.fromApi(PublicApi) as OpenApiSpec
for (const [method, path] of [
["get", "/api/connector"],
["get", "/api/connector/{connectorID}"],
["post", "/api/connector/{connectorID}/connect/key"],
["post", "/api/connector/{connectorID}/connect/oauth"],
["get", "/api/connector/oauth/{attemptID}"],
["post", "/api/connector/oauth/{attemptID}/complete"],
["delete", "/api/connector/oauth/{attemptID}"],
] as const) {
expect(spec.paths[path]?.[method], `${method.toUpperCase()} ${path}`).toBeDefined()
}
for (const path of [
"/api/connector/{connectorID}/connect/key",
"/api/connector/{connectorID}/connect/oauth",
"/api/connector/oauth/{attemptID}/complete",
]) {
expect(spec.paths[path]?.post?.requestBody?.required, path).toBe(true)
}
})
test("does not rewrite /api endpoint errors to legacy error components", () => {
const spec = OpenApi.fromApi(PublicApi) as OpenApiSpec
const refs = v2Operations(spec)