mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-22 06:42:19 +03:00
* feat(core): improve observability for dual-auth fallback execution
* refactor(executors): keep the clinepass auth decision in buildClinepassHeaders
The clinepass case no longer re-decides OAuth vs BYOK off
credentials.authType; it always delegates to buildClinepassHeaders(),
which already keys the decision off credentials.accessToken, and only
the debug log line branches. The OAuth test now uses the real credential
shape ({ accessToken }) instead of an OAuth token stored in apiKey, and
a parity test pins the executor output to buildClinepassHeaders() for
both credential shapes so the two paths cannot drift apart.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
180 lines
7.1 KiB
TypeScript
180 lines
7.1 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import {
|
|
applyClineProtocolHeaders,
|
|
buildClineHeaders,
|
|
buildClinepassHeaders,
|
|
getClineAccessToken,
|
|
getClineAuthorizationHeader,
|
|
resolveClineTaskId,
|
|
} from "../../src/shared/utils/clineAuth.ts";
|
|
import { buildProviderHeaders } from "../../open-sse/services/provider.ts";
|
|
import { DefaultExecutor } from "../../open-sse/executors/default.ts";
|
|
|
|
test("getClineAccessToken prefixes the token with workos:", () => {
|
|
assert.equal(getClineAccessToken("abc123"), "workos:abc123");
|
|
});
|
|
|
|
test("getClineAccessToken is idempotent when already prefixed", () => {
|
|
assert.equal(getClineAccessToken("workos:abc123"), "workos:abc123");
|
|
});
|
|
|
|
test("getClineAccessToken trims and rejects empty / non-string input", () => {
|
|
assert.equal(getClineAccessToken(" abc123 "), "workos:abc123");
|
|
assert.equal(getClineAccessToken(" "), "");
|
|
assert.equal(getClineAccessToken(""), "");
|
|
assert.equal(getClineAccessToken(undefined), "");
|
|
assert.equal(getClineAccessToken(null), "");
|
|
assert.equal(getClineAccessToken(42), "");
|
|
});
|
|
|
|
test("getClineAuthorizationHeader builds a workos-prefixed bearer header", () => {
|
|
assert.equal(getClineAuthorizationHeader("abc123"), "Bearer workos:abc123");
|
|
assert.equal(getClineAuthorizationHeader(""), "");
|
|
});
|
|
|
|
test("buildClineHeaders emits the full cline client header set", () => {
|
|
const headers = buildClineHeaders("abc123", {}, { taskId: "task-123" });
|
|
assert.equal(headers.Authorization, "Bearer workos:abc123");
|
|
assert.equal(headers["HTTP-Referer"], "https://cline.bot");
|
|
assert.equal(headers["X-Title"], "Cline");
|
|
assert.equal(headers["X-CLIENT-TYPE"], "omniroute");
|
|
assert.equal(headers["X-Task-ID"], "task-123");
|
|
assert.equal(headers["X-IS-MULTIROOT"], "false");
|
|
assert.ok(/^Cline\//.test(headers["User-Agent"]));
|
|
assert.ok(!/9router/i.test(JSON.stringify(headers)));
|
|
});
|
|
|
|
test("buildClineHeaders merges extra headers and omits Authorization with no token", () => {
|
|
const headers = buildClineHeaders("", {
|
|
Accept: "application/json",
|
|
"x-task-id": "configured-task-must-not-leak",
|
|
});
|
|
assert.equal(headers.Accept, "application/json");
|
|
assert.ok(!("Authorization" in headers));
|
|
assert.ok(!("X-Task-ID" in headers));
|
|
assert.ok(!("x-task-id" in headers));
|
|
// Client-identification headers are still present even without a token.
|
|
assert.equal(headers["X-CLIENT-TYPE"], "omniroute");
|
|
});
|
|
|
|
test("resolveClineTaskId forwards client task identity but does not invent one", () => {
|
|
assert.equal(resolveClineTaskId({ "x-task-id": "client-task-123" }), "client-task-123");
|
|
assert.equal(resolveClineTaskId({}), undefined);
|
|
assert.equal(resolveClineTaskId(null), undefined);
|
|
});
|
|
|
|
test("required Cline protocol headers override conflicting configured casing", () => {
|
|
const headers = applyClineProtocolHeaders(
|
|
{
|
|
"user-agent": "other-client/1",
|
|
"x-client-type": "other-client",
|
|
"x-task-id": "stored-task",
|
|
},
|
|
{ clientVersion: "3.8.49", taskId: "request-task" }
|
|
);
|
|
|
|
assert.equal(headers["User-Agent"], "Cline/3.8.49");
|
|
assert.equal(headers["X-CLIENT-TYPE"], "omniroute");
|
|
assert.equal(headers["X-Task-ID"], "request-task");
|
|
assert.ok(!("user-agent" in headers));
|
|
assert.ok(!("x-client-type" in headers));
|
|
assert.ok(!("x-task-id" in headers));
|
|
});
|
|
|
|
test("ClinePass BYOK and OAuth auth modes both carry the full protocol headers", () => {
|
|
const byok = buildClinepassHeaders({ apiKey: "sk-pass" }, undefined, {
|
|
taskId: "task-byok",
|
|
});
|
|
assert.equal(byok.Authorization, "Bearer sk-pass");
|
|
assert.equal(byok["X-Task-ID"], "task-byok");
|
|
assert.equal(byok["X-CLIENT-TYPE"], "omniroute");
|
|
|
|
const oauth = buildClinepassHeaders({ accessToken: "oauth-token" }, undefined, {
|
|
taskId: "task-oauth",
|
|
});
|
|
assert.equal(oauth.Authorization, "Bearer workos:oauth-token");
|
|
assert.equal(oauth["X-Task-ID"], "task-oauth");
|
|
assert.equal(oauth["X-CLIENT-TYPE"], "omniroute");
|
|
});
|
|
|
|
test("buildProviderHeaders uses the cline workos auth token shape", () => {
|
|
const headers = buildProviderHeaders("cline", { apiKey: "tok-abc" }, true);
|
|
assert.equal(headers.Authorization, "Bearer workos:tok-abc");
|
|
assert.equal(headers["HTTP-Referer"], "https://cline.bot");
|
|
assert.equal(headers["X-CLIENT-TYPE"], "omniroute");
|
|
});
|
|
|
|
test("buildProviderHeaders honors an accessToken for cline", () => {
|
|
const headers = buildProviderHeaders("cline", { accessToken: "acc-xyz" }, false);
|
|
assert.equal(headers.Authorization, "Bearer workos:acc-xyz");
|
|
});
|
|
|
|
test("DefaultExecutor.buildHeaders uses the cline workos auth token shape", () => {
|
|
const executor = new DefaultExecutor("cline");
|
|
const headers = executor.buildHeaders({ apiKey: "tok-abc" }, true, {
|
|
"X-Task-ID": "task-from-client",
|
|
});
|
|
assert.equal(headers.Authorization, "Bearer workos:tok-abc");
|
|
assert.equal(headers["HTTP-Referer"], "https://cline.bot");
|
|
assert.equal(headers["X-CLIENT-TYPE"], "omniroute");
|
|
assert.equal(headers["X-Title"], "Cline");
|
|
assert.equal(headers["X-Task-ID"], "task-from-client");
|
|
|
|
const withoutTaskId = executor.buildHeaders({ apiKey: "tok-abc" }, true, {});
|
|
assert.ok(!("X-Task-ID" in withoutTaskId));
|
|
});
|
|
|
|
test("DefaultExecutor labels internal health checks separately from user traffic", () => {
|
|
const executor = new DefaultExecutor("cline");
|
|
const headers = executor.buildHeaders({ apiKey: "tok-abc" }, true, {
|
|
"X-Internal-Test": "combo-health-check",
|
|
});
|
|
|
|
assert.equal(headers["X-CLIENT-TYPE"], "omniroute-internal-health-check");
|
|
|
|
// BaseExecutor reapplies the required protocol headers immediately before dispatch.
|
|
applyClineProtocolHeaders(headers, { taskId: headers["X-Task-ID"] });
|
|
assert.equal(headers["X-CLIENT-TYPE"], "omniroute-internal-health-check");
|
|
});
|
|
|
|
test("DefaultExecutor handles dual-auth logging for clinepass provider", () => {
|
|
const executor = new DefaultExecutor("clinepass");
|
|
|
|
// API key auth mode
|
|
const apiKeyHeaders = executor.buildHeaders(
|
|
{ apiKey: "sk-cline-123", authType: "apikey" },
|
|
true,
|
|
{}
|
|
);
|
|
assert.equal(apiKeyHeaders["Authorization"], "Bearer sk-cline-123");
|
|
|
|
// OAuth token auth mode — real OAuth credential shape (accessToken, not apiKey;
|
|
// see #11828 review) so this exercises the effectiveKey || credentials?.accessToken
|
|
// fallback that actually runs in production.
|
|
const oauthHeaders = executor.buildHeaders(
|
|
{ accessToken: "workos_tok_456", authType: "oauth" },
|
|
true,
|
|
{}
|
|
);
|
|
assert.equal(oauthHeaders["Authorization"], "Bearer workos:workos_tok_456");
|
|
});
|
|
|
|
test("DefaultExecutor clinepass authType branch matches buildClinepassHeaders() directly (parity)", () => {
|
|
const executor = new DefaultExecutor("clinepass");
|
|
|
|
const apiKeyCredentials = { apiKey: "sk-cline-789", authType: "apikey" };
|
|
const oauthCredentials = { accessToken: "workos_tok_789", authType: "oauth" };
|
|
|
|
for (const credentials of [apiKeyCredentials, oauthCredentials]) {
|
|
const viaExecutor = executor.buildHeaders(credentials, true, {});
|
|
const viaDirectCall = buildClinepassHeaders(credentials, credentials.apiKey);
|
|
assert.equal(
|
|
viaExecutor["Authorization"],
|
|
viaDirectCall["Authorization"],
|
|
`Authorization mismatch for ${JSON.stringify(credentials)}`
|
|
);
|
|
}
|
|
});
|