fix: make opencode iframe auth traceable

This commit is contained in:
UniDesk Codex
2026-06-30 09:32:26 +08:00
parent 8423316ebe
commit 4e2aae4d4d
3 changed files with 482 additions and 25 deletions
@@ -500,10 +500,15 @@ test("cloud web injects trace explorer runtime config from env", async () => {
});
test("cloud web OpenCode proxy requires an authenticated HWLAB session", async () => {
let authRequests = 0;
const authRequests = [];
let opencodeRequests = 0;
const cloudApi = createServer((request, response) => {
authRequests += 1;
authRequests.push({
traceparent: request.headers.traceparent,
otelTraceId: request.headers["x-hwlab-otel-trace-id"],
requestId: request.headers["x-request-id"],
sourceServiceId: request.headers["x-source-service-id"]
});
request.resume();
response.writeHead(401, { "content-type": "application/json" });
response.end(JSON.stringify({ authenticated: false }));
@@ -539,8 +544,19 @@ test("cloud web OpenCode proxy requires an authenticated HWLAB session", async (
try {
const response = await fetch(`${serverUrl(cloudWeb)}/`, { headers: { accept: "text/html" } });
assert.equal(response.status, 401);
assert.equal((await response.json()).error, "opencode_auth_required");
assert.equal(authRequests, 1);
const body = await response.json();
assert.equal(body.error, "opencode_auth_required");
assert.match(response.headers.get("traceparent") ?? "", /^00-[0-9a-f]{32}-[0-9a-f]{16}-01$/u);
assert.match(response.headers.get("x-hwlab-otel-trace-id") ?? "", /^[0-9a-f]{32}$/u);
assert.match(response.headers.get("x-request-id") ?? "", /^req_[0-9a-f]{32}$/u);
assert.equal(body.diagnostic.traceId, response.headers.get("x-hwlab-otel-trace-id"));
assert.equal(body.diagnostic.requestId, response.headers.get("x-request-id"));
assert.deepEqual(authRequests, [{
traceparent: response.headers.get("traceparent"),
otelTraceId: response.headers.get("x-hwlab-otel-trace-id"),
requestId: response.headers.get("x-request-id"),
sourceServiceId: "hwlab-cloud-web"
}]);
assert.equal(opencodeRequests, 0);
} finally {
await close(cloudWeb);
@@ -549,6 +565,89 @@ test("cloud web OpenCode proxy requires an authenticated HWLAB session", async (
}
});
test("cloud web OpenCode frame-url endpoint mints traced tickets", async () => {
const restoreEnv = withEnv({
HWLAB_CLOUD_WEB_DISPLAY_TIME_ZONE: "Asia/Shanghai",
HWLAB_CLOUD_WEB_DISPLAY_TIME_LOCALE: "zh-CN",
HWLAB_CLOUD_WEB_DISPLAY_TIME_LABEL: "北京时间",
HWLAB_CLOUD_WEB_OPENCODE_URL: "https://opencode.example.test"
});
const cloudApiRequests = [];
const opencodeRequests = [];
const cloudApi = createServer((request, response) => {
cloudApiRequests.push({
cookie: request.headers.cookie,
traceparent: request.headers.traceparent,
otelTraceId: request.headers["x-hwlab-otel-trace-id"],
requestId: request.headers["x-request-id"],
sourceServiceId: request.headers["x-source-service-id"]
});
request.resume();
response.writeHead(200, { "content-type": "application/json" });
response.end(JSON.stringify({ authenticated: request.headers.cookie === "hwlab_session=session-a" }));
});
const opencode = createServer((request, response) => {
opencodeRequests.push({ url: request.url, cookie: request.headers.cookie });
request.resume();
response.writeHead(200, { "content-type": "text/plain" });
response.end("opencode ok\n");
});
await listen(cloudApi);
await listen(opencode);
const cloudWeb = createCloudWebServer({
serviceId: "hwlab-cloud-web",
roots: [],
cloudApiBaseUrl: serverUrl(cloudApi),
cloudApiProxyTimeoutMs: 1000,
opencodeUpstreamUrl: serverUrl(opencode),
opencodeProxyHost: "",
opencodeProxyTimeoutMs: 1000,
opencodeUsername: "oc_user",
opencodePassword: "oc_password",
healthPayload: () => ({ status: "ok" }),
sendJson(response, statusCode, body) {
const payload = JSON.stringify(body);
response.writeHead(statusCode, { "content-type": "application/json", "content-length": Buffer.byteLength(payload) });
response.end(payload);
}
});
await listen(cloudWeb);
try {
const response = await fetch(`${serverUrl(cloudWeb)}/opencode/frame-url`, {
headers: { accept: "application/json", cookie: "hwlab_session=session-a", "x-request-id": "req_opencode_frame_url" }
});
assert.equal(response.status, 200);
assert.equal(response.headers.get("x-request-id"), "req_opencode_frame_url");
assert.match(response.headers.get("traceparent") ?? "", /^00-[0-9a-f]{32}-[0-9a-f]{16}-01$/u);
const body = await response.json();
const frameUrl = new URL(body.url);
const ticket = frameUrl.searchParams.get("hwlab_opencode_ticket");
assert.ok(ticket, "dynamic endpoint should append an OpenCode ticket");
assert.equal(body.diagnostic.traceId, response.headers.get("x-hwlab-otel-trace-id"));
assert.deepEqual(cloudApiRequests, [{
cookie: "hwlab_session=session-a",
traceparent: response.headers.get("traceparent"),
otelTraceId: response.headers.get("x-hwlab-otel-trace-id"),
requestId: "req_opencode_frame_url",
sourceServiceId: "hwlab-cloud-web"
}]);
const proxied = await fetch(`${serverUrl(cloudWeb)}/_opencode/?hwlab_opencode_ticket=${encodeURIComponent(ticket)}`, {
headers: { accept: "text/plain" }
});
assert.equal(proxied.status, 200);
assert.equal(await proxied.text(), "opencode ok\n");
assert.deepEqual(opencodeRequests, [{ url: "/", cookie: undefined }]);
} finally {
restoreEnv();
await close(cloudWeb);
await close(opencode);
await close(cloudApi);
}
});
test("cloud web OpenCode proxy injects upstream Basic Auth without forwarding HWLAB cookie", async () => {
const opencodeRequests = [];
const cloudApi = createServer((request, response) => {