源码快照 @ 2026-09-02 (source-only, 剔除非源码素材)
This commit is contained in:
@@ -0,0 +1,766 @@
|
||||
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
||||
|
||||
import {
|
||||
buildDenAuthUrl,
|
||||
createDenClient,
|
||||
getDenMcpUrl,
|
||||
initializeDenBootstrapConfig,
|
||||
readDenBootstrapConfig,
|
||||
readDenSettings,
|
||||
resolveDenBaseUrls,
|
||||
} from "../src/app/lib/den";
|
||||
import {
|
||||
hydrateOpenworkServerSettingsFromEnv,
|
||||
readOpenworkServerSettings,
|
||||
} from "../src/app/lib/openwork-server";
|
||||
import { createOpenworkServerStore } from "../src/react-app/domains/connections/openwork-server-store";
|
||||
import { buildOpenworkHealthHeaders } from "../src/react-app/kernel/server-provider";
|
||||
import {
|
||||
isStaleStoredDesktopConnection,
|
||||
resolveOpenworkConnection,
|
||||
} from "../src/react-app/shell/openwork-connection";
|
||||
|
||||
const originalWindow = globalThis.window;
|
||||
const originalFetch = globalThis.fetch;
|
||||
const originalDeployment = process.env.VITE_OPENWORK_DEPLOYMENT;
|
||||
|
||||
function restoreEnv(key: string, value: string | undefined) {
|
||||
if (value === undefined) delete process.env[key];
|
||||
else process.env[key] = value;
|
||||
}
|
||||
|
||||
function memoryStorage(): Storage {
|
||||
const map = new Map<string, string>();
|
||||
return {
|
||||
get length() {
|
||||
return map.size;
|
||||
},
|
||||
clear() {
|
||||
map.clear();
|
||||
},
|
||||
getItem(key: string) {
|
||||
return map.get(key) ?? null;
|
||||
},
|
||||
key(index: number) {
|
||||
return Array.from(map.keys())[index] ?? null;
|
||||
},
|
||||
removeItem(key: string) {
|
||||
map.delete(key);
|
||||
},
|
||||
setItem(key: string, value: string) {
|
||||
map.set(key, value);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function getRequestUrl(input: RequestInfo | URL): string {
|
||||
if (input instanceof URL) return input.toString();
|
||||
if (typeof input === "string") return input;
|
||||
return input.url;
|
||||
}
|
||||
|
||||
function createTestOpenworkServerStore(startupPreference: "local" | "server" = "server") {
|
||||
return createOpenworkServerStore({
|
||||
startupPreference: () => startupPreference,
|
||||
documentVisible: () => true,
|
||||
developerMode: () => false,
|
||||
runtimeWorkspaceId: () => "workspace_test",
|
||||
activeClient: () => null,
|
||||
selectedWorkspaceDisplay: () => ({
|
||||
id: "workspace_test",
|
||||
name: "Test workspace",
|
||||
path: "/tmp/workspace_test",
|
||||
preset: "default",
|
||||
workspaceType: "local",
|
||||
}),
|
||||
restartLocalServer: async () => false,
|
||||
createRemoteWorkspaceFlow: async () => false,
|
||||
});
|
||||
}
|
||||
|
||||
function installWindow(options: {
|
||||
origin: string;
|
||||
gateway?: boolean;
|
||||
bootstrapToken?: string;
|
||||
electronInfo?: {
|
||||
baseUrl: string;
|
||||
ownerToken: string;
|
||||
clientToken?: string;
|
||||
hostToken?: string;
|
||||
};
|
||||
/** Raw openworkServerInfo response for non-ready/restarting server states. */
|
||||
electronServerInfoRaw?: Record<string, unknown>;
|
||||
/** Simulate a desktop bridge whose openworkServerInfo call fails outright. */
|
||||
electronServerInfoError?: boolean;
|
||||
}) {
|
||||
const localStorage = memoryStorage();
|
||||
const electronBridgeInstalled =
|
||||
options.electronInfo || options.electronServerInfoRaw || options.electronServerInfoError;
|
||||
Object.defineProperty(globalThis, "window", {
|
||||
configurable: true,
|
||||
value: {
|
||||
localStorage,
|
||||
dispatchEvent: () => true,
|
||||
setTimeout: () => 1,
|
||||
clearTimeout: () => undefined,
|
||||
location: { origin: options.origin },
|
||||
__OPENWORK_GATEWAY__: options.gateway ? { version: 1 } : undefined,
|
||||
__OPENWORK_BOOTSTRAP__: options.bootstrapToken ? { token: options.bootstrapToken } : undefined,
|
||||
__OPENWORK_ELECTRON__: electronBridgeInstalled
|
||||
? {
|
||||
invokeDesktop: async (command: string) => {
|
||||
if (command !== "openworkServerInfo") {
|
||||
throw new Error(`Unexpected desktop command: ${command}`);
|
||||
}
|
||||
if (options.electronServerInfoError) {
|
||||
throw new Error("desktop bridge unavailable");
|
||||
}
|
||||
if (options.electronServerInfoRaw) {
|
||||
return options.electronServerInfoRaw;
|
||||
}
|
||||
return {
|
||||
running: true,
|
||||
baseUrl: options.electronInfo?.baseUrl,
|
||||
ownerToken: options.electronInfo?.ownerToken,
|
||||
clientToken: options.electronInfo?.clientToken,
|
||||
hostToken: options.electronInfo?.hostToken,
|
||||
};
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
return localStorage;
|
||||
}
|
||||
|
||||
describe("gateway runtime mode", () => {
|
||||
beforeEach(() => {
|
||||
process.env.VITE_OPENWORK_DEPLOYMENT = "web";
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
Object.defineProperty(globalThis, "window", {
|
||||
configurable: true,
|
||||
value: originalWindow,
|
||||
});
|
||||
Object.defineProperty(globalThis, "fetch", {
|
||||
configurable: true,
|
||||
value: originalFetch,
|
||||
});
|
||||
if (originalDeployment === undefined) {
|
||||
delete process.env.VITE_OPENWORK_DEPLOYMENT;
|
||||
} else {
|
||||
process.env.VITE_OPENWORK_DEPLOYMENT = originalDeployment;
|
||||
}
|
||||
});
|
||||
|
||||
test("resolves OpenWork server traffic through the gateway origin with the Den session token", async () => {
|
||||
const storage = installWindow({ origin: "https://web.openworklabs.com", gateway: true });
|
||||
storage.setItem("openwork.den.authToken", "den-session-token");
|
||||
storage.setItem("openwork.server.urlOverride", "https://direct-instance.example.com");
|
||||
storage.setItem("openwork.server.token", "stale-instance-token");
|
||||
|
||||
const connection = await resolveOpenworkConnection();
|
||||
|
||||
expect(connection).toEqual({
|
||||
normalizedBaseUrl: "https://web.openworklabs.com",
|
||||
resolvedToken: "den-session-token",
|
||||
resolvedHostToken: "",
|
||||
hostInfo: null,
|
||||
source: "gateway",
|
||||
});
|
||||
});
|
||||
|
||||
test("keeps the OpenWork server snapshot stable when options have not changed", () => {
|
||||
installWindow({ origin: "https://web.openworklabs.com", gateway: true });
|
||||
const store = createTestOpenworkServerStore();
|
||||
const initialSnapshot = store.getSnapshot();
|
||||
let notifications = 0;
|
||||
const unsubscribe = store.subscribe(() => {
|
||||
notifications += 1;
|
||||
});
|
||||
|
||||
store.syncFromOptions();
|
||||
|
||||
expect(store.getSnapshot()).toBe(initialSnapshot);
|
||||
expect(notifications).toBe(0);
|
||||
|
||||
store.updateOpenworkServerSettings({
|
||||
urlOverride: "https://instance.example.com",
|
||||
token: "instance-token",
|
||||
});
|
||||
|
||||
expect(store.getSnapshot()).not.toBe(initialSnapshot);
|
||||
expect(notifications).toBe(1);
|
||||
unsubscribe();
|
||||
});
|
||||
|
||||
test("keeps Den web on the configured origin and Den API calls on the gateway origin", () => {
|
||||
const storage = installWindow({ origin: "https://gw.example", gateway: true });
|
||||
storage.setItem("openwork.den.baseUrl", "https://app.openworklabs.com");
|
||||
storage.setItem("openwork.den.authToken", "den-session-token");
|
||||
|
||||
expect(resolveDenBaseUrls("https://gw.example")).toEqual({
|
||||
baseUrl: "https://app.openworklabs.com",
|
||||
apiBaseUrl: "https://gw.example/api/den",
|
||||
});
|
||||
expect(readDenSettings().baseUrl).toBe("https://app.openworklabs.com");
|
||||
expect(readDenSettings().apiBaseUrl).toBe("https://gw.example/api/den");
|
||||
expect(readDenSettings().authToken).toBe("den-session-token");
|
||||
});
|
||||
|
||||
test("builds web auth URLs on the Den web origin with the gateway return origin", () => {
|
||||
installWindow({ origin: "https://gw.example", gateway: true });
|
||||
|
||||
const authUrl = new URL(buildDenAuthUrl(readDenSettings().baseUrl, "sign-up"));
|
||||
|
||||
expect(authUrl.origin).toBe("https://app.openworklabs.com");
|
||||
expect(authUrl.searchParams.get("mode")).toBe("sign-up");
|
||||
expect(authUrl.searchParams.get("webAuth")).toBe("1");
|
||||
expect(authUrl.searchParams.get("webAuthReturn")).toBe("https://gw.example");
|
||||
});
|
||||
|
||||
test("routes Den auth API paths to Den web and v1 paths through the gateway API", async () => {
|
||||
installWindow({ origin: "https://gw.example", gateway: true });
|
||||
const requestedUrls: string[] = [];
|
||||
Object.defineProperty(globalThis, "fetch", {
|
||||
configurable: true,
|
||||
value: async (input: RequestInfo | URL) => {
|
||||
requestedUrls.push(getRequestUrl(input));
|
||||
return new Response(JSON.stringify({
|
||||
user: { id: "user_test", email: "user@example.com" },
|
||||
token: "tok_test",
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const client = createDenClient({ baseUrl: readDenSettings().baseUrl, token: "tok_test" });
|
||||
await client.signInEmail("user@example.com", "password");
|
||||
await client.getSession();
|
||||
|
||||
expect(requestedUrls).toEqual([
|
||||
"https://app.openworklabs.com/api/auth/sign-in/email",
|
||||
"https://gw.example/api/den/v1/me",
|
||||
]);
|
||||
});
|
||||
|
||||
test("reads Den-authored Web access through the gateway for the selected organization", async () => {
|
||||
installWindow({ origin: "https://gw.example", gateway: true });
|
||||
const requests: Array<{
|
||||
url: string;
|
||||
authorization: string | null;
|
||||
organizationId: string | null;
|
||||
}> = [];
|
||||
Object.defineProperty(globalThis, "fetch", {
|
||||
configurable: true,
|
||||
value: async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const url = getRequestUrl(input);
|
||||
const headers = new Headers(init?.headers);
|
||||
requests.push({
|
||||
url,
|
||||
authorization: headers.get("authorization"),
|
||||
organizationId: headers.get("x-openwork-org-id"),
|
||||
});
|
||||
if (new URL(url).pathname === "/api/den/v1/org") {
|
||||
return Response.json({ capabilities: { openworkWeb: true } });
|
||||
}
|
||||
return Response.json({
|
||||
billing: {
|
||||
stripe: {
|
||||
web: {
|
||||
hasAccess: true,
|
||||
accessSource: "complimentary",
|
||||
hasEligibleSubscription: false,
|
||||
complimentaryAccess: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const access = await createDenClient({
|
||||
baseUrl: readDenSettings().baseUrl,
|
||||
token: "tok_test",
|
||||
}).getOpenWorkWebAccess("org_test");
|
||||
|
||||
expect(access).toEqual({ hasAccess: true, accessSource: "complimentary" });
|
||||
expect(requests).toEqual([
|
||||
{
|
||||
url: "https://gw.example/api/den/v1/org",
|
||||
authorization: "Bearer tok_test",
|
||||
organizationId: "org_test",
|
||||
},
|
||||
{
|
||||
url: "https://gw.example/api/den/v1/billing/web",
|
||||
authorization: "Bearer tok_test",
|
||||
organizationId: "org_test",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test("keeps Web locked without calling billing when an older Den omits the capability", async () => {
|
||||
installWindow({ origin: "https://gw.example", gateway: true });
|
||||
const requestedUrls: string[] = [];
|
||||
Object.defineProperty(globalThis, "fetch", {
|
||||
configurable: true,
|
||||
value: async (input: RequestInfo | URL) => {
|
||||
requestedUrls.push(getRequestUrl(input));
|
||||
return Response.json({ capabilities: {} });
|
||||
},
|
||||
});
|
||||
|
||||
const access = await createDenClient({
|
||||
baseUrl: readDenSettings().baseUrl,
|
||||
token: "tok_test",
|
||||
}).getOpenWorkWebAccess("org_test");
|
||||
|
||||
expect(access).toEqual({ hasAccess: false, accessSource: null });
|
||||
expect(requestedUrls).toEqual(["https://gw.example/api/den/v1/org"]);
|
||||
});
|
||||
|
||||
test("uses the gateway Den API proxy for MCP", () => {
|
||||
installWindow({ origin: "https://gw.example", gateway: true });
|
||||
|
||||
expect(getDenMcpUrl()).toBe("https://gw.example/api/den/mcp");
|
||||
});
|
||||
|
||||
test("returns a stable gateway bootstrap snapshot for React external stores", () => {
|
||||
installWindow({ origin: "https://web.openworklabs.com", gateway: true });
|
||||
|
||||
const first = readDenBootstrapConfig();
|
||||
const second = readDenBootstrapConfig();
|
||||
|
||||
expect(second).toBe(first);
|
||||
expect(first.baseUrl).toBe("https://app.openworklabs.com");
|
||||
expect(first.apiBaseUrl).toBe("https://web.openworklabs.com/api/den");
|
||||
});
|
||||
|
||||
test("does not hydrate an instance bootstrap token into server storage behind the gateway", () => {
|
||||
const storage = installWindow({
|
||||
origin: "https://web.openworklabs.com",
|
||||
gateway: true,
|
||||
bootstrapToken: "instance-token-must-not-store",
|
||||
});
|
||||
|
||||
hydrateOpenworkServerSettingsFromEnv();
|
||||
|
||||
expect(storage.getItem("openwork.server.token")).toBeNull();
|
||||
expect(readOpenworkServerSettings().token).toBeUndefined();
|
||||
});
|
||||
|
||||
test("uses same-origin and the Den bearer for OpenWork server store env calls behind the gateway", async () => {
|
||||
const storage = installWindow({ origin: "https://gw.example", gateway: true });
|
||||
storage.setItem("openwork.den.authToken", "den-session-token");
|
||||
storage.setItem("openwork.server.urlOverride", "https://direct-instance.example.com");
|
||||
storage.setItem("openwork.server.token", "stale-instance-token");
|
||||
storage.setItem("openwork.server.hostToken", "stale-host-token");
|
||||
const requests: Array<{ url: string; authorization: string | null; hostToken: string | null }> = [];
|
||||
Object.defineProperty(globalThis, "fetch", {
|
||||
configurable: true,
|
||||
value: async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const headers = new Headers(init?.headers);
|
||||
requests.push({
|
||||
url: getRequestUrl(input),
|
||||
authorization: headers.get("authorization"),
|
||||
hostToken: headers.get("x-openwork-host-token"),
|
||||
});
|
||||
return new Response(JSON.stringify({ runtimeKey: "runtime-a", pendingChanges: false, ok: true, count: 1 }), {
|
||||
status: 200,
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const store = createTestOpenworkServerStore();
|
||||
const snapshot = store.getSnapshot();
|
||||
const client = snapshot.openworkServerClient;
|
||||
if (!client) throw new Error("Expected a gateway OpenWork server client");
|
||||
|
||||
expect(snapshot.openworkServerBaseUrl).toBe("https://gw.example");
|
||||
expect(snapshot.openworkServerAuth.token).toBe("den-session-token");
|
||||
expect(snapshot.openworkServerAuth.hostToken).toBeUndefined();
|
||||
expect(client.baseUrl).toBe("https://gw.example");
|
||||
expect(client.token).toBe("den-session-token");
|
||||
|
||||
await client.getUserEnvStatus("runtime-a");
|
||||
await client.upsertUserEnv([{ key: "OPENAI_API_KEY", value: "sk-test" }]);
|
||||
|
||||
expect(requests).toEqual([
|
||||
{
|
||||
url: "https://gw.example/env/status?runtimeKey=runtime-a",
|
||||
authorization: "Bearer den-session-token",
|
||||
hostToken: null,
|
||||
},
|
||||
{
|
||||
url: "https://gw.example/env",
|
||||
authorization: "Bearer den-session-token",
|
||||
hostToken: null,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test("uses the Den bearer for same-origin OpenCode health polling behind the gateway", () => {
|
||||
const storage = installWindow({ origin: "https://gw.example", gateway: true });
|
||||
storage.setItem("openwork.den.authToken", "den-session-token");
|
||||
storage.setItem("openwork.server.token", "stale-instance-token");
|
||||
|
||||
expect(buildOpenworkHealthHeaders("https://gw.example/opencode")).toEqual({
|
||||
Authorization: "Bearer den-session-token",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("non-gateway connection modes", () => {
|
||||
beforeEach(() => {
|
||||
process.env.VITE_OPENWORK_DEPLOYMENT = "web";
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
Object.defineProperty(globalThis, "window", {
|
||||
configurable: true,
|
||||
value: originalWindow,
|
||||
});
|
||||
Object.defineProperty(globalThis, "fetch", {
|
||||
configurable: true,
|
||||
value: originalFetch,
|
||||
});
|
||||
if (originalDeployment === undefined) {
|
||||
delete process.env.VITE_OPENWORK_DEPLOYMENT;
|
||||
} else {
|
||||
process.env.VITE_OPENWORK_DEPLOYMENT = originalDeployment;
|
||||
}
|
||||
});
|
||||
|
||||
test("direct instance bootstrap hydration and same-origin resolution are unchanged without the marker", async () => {
|
||||
installWindow({ origin: "https://instance.example.com", bootstrapToken: "instance-token" });
|
||||
|
||||
hydrateOpenworkServerSettingsFromEnv();
|
||||
const connection = await resolveOpenworkConnection();
|
||||
|
||||
expect(readOpenworkServerSettings().token).toBe("instance-token");
|
||||
expect(connection.normalizedBaseUrl).toBe("https://instance.example.com");
|
||||
expect(connection.resolvedToken).toBe("instance-token");
|
||||
expect(connection.source).toBe("same-origin");
|
||||
});
|
||||
|
||||
test("force-env settings overwrite stale localStorage openwork-server credentials", () => {
|
||||
const previous = {
|
||||
url: process.env.VITE_OPENWORK_URL,
|
||||
port: process.env.VITE_OPENWORK_PORT,
|
||||
token: process.env.VITE_OPENWORK_TOKEN,
|
||||
hostToken: process.env.VITE_OPENWORK_HOST_TOKEN,
|
||||
force: process.env.VITE_OPENWORK_FORCE_ENV_SETTINGS,
|
||||
};
|
||||
process.env.VITE_OPENWORK_URL = "http://127.0.0.1:8787";
|
||||
process.env.VITE_OPENWORK_PORT = "8787";
|
||||
process.env.VITE_OPENWORK_TOKEN = "fresh-token";
|
||||
process.env.VITE_OPENWORK_HOST_TOKEN = "fresh-host-token";
|
||||
process.env.VITE_OPENWORK_FORCE_ENV_SETTINGS = "1";
|
||||
|
||||
const storage = installWindow({ origin: "http://127.0.0.1:5173" });
|
||||
storage.setItem("openwork.server.urlOverride", "http://127.0.0.1:9999");
|
||||
storage.setItem("openwork.server.token", "stale-token");
|
||||
storage.setItem("openwork.server.hostToken", "stale-host-token");
|
||||
|
||||
try {
|
||||
hydrateOpenworkServerSettingsFromEnv();
|
||||
expect(readOpenworkServerSettings()).toEqual({
|
||||
urlOverride: "http://127.0.0.1:8787",
|
||||
portOverride: 8787,
|
||||
token: "fresh-token",
|
||||
hostToken: "fresh-host-token",
|
||||
remoteAccessEnabled: false,
|
||||
});
|
||||
} finally {
|
||||
restoreEnv("VITE_OPENWORK_URL", previous.url);
|
||||
restoreEnv("VITE_OPENWORK_PORT", previous.port);
|
||||
restoreEnv("VITE_OPENWORK_TOKEN", previous.token);
|
||||
restoreEnv("VITE_OPENWORK_HOST_TOKEN", previous.hostToken);
|
||||
restoreEnv("VITE_OPENWORK_FORCE_ENV_SETTINGS", previous.force);
|
||||
}
|
||||
});
|
||||
|
||||
test("force-env without a VITE host token clears a leftover browser host token", () => {
|
||||
const previous = {
|
||||
url: process.env.VITE_OPENWORK_URL,
|
||||
port: process.env.VITE_OPENWORK_PORT,
|
||||
token: process.env.VITE_OPENWORK_TOKEN,
|
||||
hostToken: process.env.VITE_OPENWORK_HOST_TOKEN,
|
||||
force: process.env.VITE_OPENWORK_FORCE_ENV_SETTINGS,
|
||||
};
|
||||
process.env.VITE_OPENWORK_URL = "http://127.0.0.1:8787";
|
||||
process.env.VITE_OPENWORK_PORT = "8787";
|
||||
process.env.VITE_OPENWORK_TOKEN = "fresh-token";
|
||||
delete process.env.VITE_OPENWORK_HOST_TOKEN;
|
||||
process.env.VITE_OPENWORK_FORCE_ENV_SETTINGS = "1";
|
||||
|
||||
const storage = installWindow({ origin: "http://127.0.0.1:5178" });
|
||||
storage.setItem("openwork.server.hostToken", "leaked-host-token");
|
||||
|
||||
try {
|
||||
hydrateOpenworkServerSettingsFromEnv();
|
||||
expect(readOpenworkServerSettings().hostToken).toBeUndefined();
|
||||
expect(storage.getItem("openwork.server.hostToken")).toBeNull();
|
||||
} finally {
|
||||
restoreEnv("VITE_OPENWORK_URL", previous.url);
|
||||
restoreEnv("VITE_OPENWORK_PORT", previous.port);
|
||||
restoreEnv("VITE_OPENWORK_TOKEN", previous.token);
|
||||
restoreEnv("VITE_OPENWORK_HOST_TOKEN", previous.hostToken);
|
||||
restoreEnv("VITE_OPENWORK_FORCE_ENV_SETTINGS", previous.force);
|
||||
}
|
||||
});
|
||||
|
||||
test("stored server settings still win without the marker", async () => {
|
||||
const storage = installWindow({ origin: "https://instance.example.com" });
|
||||
storage.setItem("openwork.server.urlOverride", "https://manual.example.com");
|
||||
storage.setItem("openwork.server.token", "manual-token");
|
||||
storage.setItem("openwork.server.hostToken", "host-token");
|
||||
|
||||
const connection = await resolveOpenworkConnection();
|
||||
|
||||
expect(connection.normalizedBaseUrl).toBe("https://manual.example.com");
|
||||
expect(connection.resolvedToken).toBe("manual-token");
|
||||
expect(connection.resolvedHostToken).toBe("");
|
||||
expect(connection.source).toBe("stored-settings");
|
||||
|
||||
const store = createTestOpenworkServerStore();
|
||||
const snapshot = store.getSnapshot();
|
||||
|
||||
expect(snapshot.openworkServerBaseUrl).toBe("https://manual.example.com");
|
||||
expect(snapshot.openworkServerAuth.token).toBe("manual-token");
|
||||
expect(snapshot.openworkServerAuth.hostToken).toBeUndefined();
|
||||
expect(snapshot.openworkServerClient?.baseUrl).toBe("https://manual.example.com");
|
||||
expect(snapshot.openworkServerClient?.token).toBe("manual-token");
|
||||
});
|
||||
|
||||
test("OpenCode health polling still uses the stored instance token without the gateway marker", () => {
|
||||
const storage = installWindow({ origin: "https://instance.example.com" });
|
||||
storage.setItem("openwork.server.token", "instance-token");
|
||||
|
||||
expect(buildOpenworkHealthHeaders("https://instance.example.com/opencode")).toEqual({
|
||||
Authorization: "Bearer instance-token",
|
||||
});
|
||||
});
|
||||
|
||||
test("plain web Den settings still use a stored custom base URL without the marker", () => {
|
||||
const storage = installWindow({ origin: "https://instance.example.com" });
|
||||
storage.setItem("openwork.den.baseUrl", "https://den.self-hosted.example.com");
|
||||
|
||||
expect(readDenSettings().baseUrl).toBe("https://den.self-hosted.example.com");
|
||||
expect(readDenSettings().apiBaseUrl).toBe("https://den.self-hosted.example.com/api/den");
|
||||
});
|
||||
|
||||
test("VITE_DEN_API_BASE_URL pins Den API calls to the proxy while sign-in stays on the web base", () => {
|
||||
const previous = process.env.VITE_DEN_API_BASE_URL;
|
||||
process.env.VITE_DEN_API_BASE_URL = "http://127.0.0.1:5178/api/den";
|
||||
installWindow({ origin: "http://127.0.0.1:5178" });
|
||||
|
||||
try {
|
||||
const settings = readDenSettings();
|
||||
expect(settings.baseUrl).toBe("https://app.openworklabs.com");
|
||||
expect(settings.apiBaseUrl).toBe("http://127.0.0.1:5178/api/den");
|
||||
|
||||
// Every Den client derives its API base the same way, so requests go
|
||||
// through the same-origin proxy even when created from the web base.
|
||||
const client = createDenClient({ baseUrl: settings.baseUrl, token: "den-token" });
|
||||
expect(client.baseUrls.apiBaseUrl).toBe("http://127.0.0.1:5178/api/den");
|
||||
expect(client.baseUrls.baseUrl).toBe("https://app.openworklabs.com");
|
||||
|
||||
// Sign-in still opens the real Den web app, not the proxy origin.
|
||||
// Loopback cannot use webAuth return URLs against hosted Den, so the
|
||||
// URL uses desktopAuth (copy link / paste grant) instead.
|
||||
const authUrl = new URL(buildDenAuthUrl(settings.baseUrl, "sign-in"));
|
||||
expect(authUrl.origin).toBe("https://app.openworklabs.com");
|
||||
expect(authUrl.searchParams.get("desktopAuth")).toBe("1");
|
||||
expect(authUrl.searchParams.get("webAuth")).toBeNull();
|
||||
} finally {
|
||||
restoreEnv("VITE_DEN_API_BASE_URL", previous);
|
||||
}
|
||||
});
|
||||
|
||||
test("loopback web auth uses desktop handoff instead of an unapprovable webAuth return URL", () => {
|
||||
installWindow({ origin: "http://127.0.0.1:5178" });
|
||||
|
||||
const authUrl = new URL(buildDenAuthUrl(readDenSettings().baseUrl, "sign-in"));
|
||||
|
||||
expect(authUrl.origin).toBe("https://app.openworklabs.com");
|
||||
expect(authUrl.searchParams.get("desktopAuth")).toBe("1");
|
||||
expect(authUrl.searchParams.get("desktopScheme")).toBe("openwork");
|
||||
expect(authUrl.searchParams.get("webAuth")).toBeNull();
|
||||
expect(authUrl.searchParams.get("webAuthReturn")).toBeNull();
|
||||
});
|
||||
|
||||
test("force-env clears a stale stored Den base URL on web bootstrap init", async () => {
|
||||
const previous = process.env.VITE_OPENWORK_FORCE_ENV_SETTINGS;
|
||||
process.env.VITE_OPENWORK_FORCE_ENV_SETTINGS = "1";
|
||||
const storage = installWindow({ origin: "http://127.0.0.1:5178" });
|
||||
storage.setItem("openwork.den.baseUrl", "http://127.0.0.1:8779");
|
||||
|
||||
try {
|
||||
await initializeDenBootstrapConfig();
|
||||
expect(storage.getItem("openwork.den.baseUrl")).toBeNull();
|
||||
expect(readDenSettings().baseUrl).toBe("https://app.openworklabs.com");
|
||||
} finally {
|
||||
restoreEnv("VITE_OPENWORK_FORCE_ENV_SETTINGS", previous);
|
||||
}
|
||||
});
|
||||
|
||||
test("desktop runtime still uses live desktop server info without the marker", async () => {
|
||||
installWindow({
|
||||
origin: "https://instance.example.com",
|
||||
electronInfo: {
|
||||
baseUrl: "http://127.0.0.1:8787",
|
||||
ownerToken: "owner-token",
|
||||
hostToken: "host-token",
|
||||
},
|
||||
});
|
||||
|
||||
const connection = await resolveOpenworkConnection();
|
||||
|
||||
expect(connection.normalizedBaseUrl).toBe("http://127.0.0.1:8787");
|
||||
expect(connection.resolvedToken).toBe("owner-token");
|
||||
expect(connection.resolvedHostToken).toBe("host-token");
|
||||
expect(connection.source).toBe("desktop-runtime");
|
||||
});
|
||||
|
||||
test("desktop reconnect persists the complete live server credential bundle", async () => {
|
||||
const storage = installWindow({
|
||||
origin: "https://instance.example.com",
|
||||
electronInfo: {
|
||||
baseUrl: "http://127.0.0.1:8787",
|
||||
ownerToken: "owner-token",
|
||||
clientToken: "live-client-token",
|
||||
hostToken: "live-host-token",
|
||||
},
|
||||
});
|
||||
storage.setItem("openwork.server.token", "stale-client-token");
|
||||
storage.setItem("openwork.server.hostToken", "stale-host-token");
|
||||
Object.defineProperty(globalThis, "fetch", {
|
||||
configurable: true,
|
||||
value: async () => new Response(JSON.stringify({ ok: true }), {
|
||||
status: 200,
|
||||
headers: { "content-type": "application/json" },
|
||||
}),
|
||||
});
|
||||
|
||||
const store = createTestOpenworkServerStore("local");
|
||||
|
||||
expect(await store.reconnectOpenworkServer()).toBe(true);
|
||||
expect(readOpenworkServerSettings().token).toBe("live-client-token");
|
||||
expect(readOpenworkServerSettings().hostToken).toBe("live-host-token");
|
||||
expect(store.getSnapshot().openworkServerAuth).toEqual({
|
||||
token: "live-client-token",
|
||||
hostToken: "live-host-token",
|
||||
});
|
||||
});
|
||||
|
||||
test("a restarting desktop server invalidates stored loopback settings instead of resolving a dead port", async () => {
|
||||
// App update / slow restart: the live runtime answers definitively, but
|
||||
// the server has not republished its base URL and tokens yet. The stored
|
||||
// loopback settings are from the previous server lifetime.
|
||||
const storage = installWindow({
|
||||
origin: "https://instance.example.com",
|
||||
electronServerInfoRaw: { running: false, baseUrl: null, ownerToken: null, clientToken: null },
|
||||
});
|
||||
storage.setItem("openwork.server.urlOverride", "http://127.0.0.1:4100");
|
||||
storage.setItem("openwork.server.token", "tok_previous_lifetime");
|
||||
|
||||
const connection = await resolveOpenworkConnection();
|
||||
|
||||
expect(connection.source).toBe("empty");
|
||||
expect(connection.normalizedBaseUrl).toBe("");
|
||||
expect(connection.resolvedToken).toBe("");
|
||||
});
|
||||
|
||||
test("a restarting desktop server keeps stored remote/manual servers as the fallback", async () => {
|
||||
const storage = installWindow({
|
||||
origin: "https://instance.example.com",
|
||||
electronServerInfoRaw: { running: false, baseUrl: null, ownerToken: null, clientToken: null },
|
||||
});
|
||||
storage.setItem("openwork.server.urlOverride", "https://manual.example.com");
|
||||
storage.setItem("openwork.server.token", "manual-token");
|
||||
|
||||
const connection = await resolveOpenworkConnection();
|
||||
|
||||
expect(connection.source).toBe("stored-settings");
|
||||
expect(connection.normalizedBaseUrl).toBe("https://manual.example.com");
|
||||
expect(connection.resolvedToken).toBe("manual-token");
|
||||
});
|
||||
|
||||
test("a failing desktop bridge still falls back to stored settings", async () => {
|
||||
// No definitive live answer: keep the pre-existing fallback so broken
|
||||
// bridges do not strand configured connections.
|
||||
const storage = installWindow({
|
||||
origin: "https://instance.example.com",
|
||||
electronServerInfoError: true,
|
||||
});
|
||||
storage.setItem("openwork.server.urlOverride", "http://127.0.0.1:4100");
|
||||
storage.setItem("openwork.server.token", "tok_stored");
|
||||
|
||||
const connection = await resolveOpenworkConnection();
|
||||
|
||||
expect(connection.source).toBe("stored-settings");
|
||||
expect(connection.normalizedBaseUrl).toBe("http://127.0.0.1:4100");
|
||||
expect(connection.resolvedToken).toBe("tok_stored");
|
||||
});
|
||||
});
|
||||
|
||||
describe("isStaleStoredDesktopConnection", () => {
|
||||
test("marks stored loopback connections stale only on a definitive not-ready answer", () => {
|
||||
expect(
|
||||
isStaleStoredDesktopConnection({
|
||||
desktopRuntime: true,
|
||||
desktopServerReportedNotReady: true,
|
||||
storedBaseUrl: "http://127.0.0.1:4100",
|
||||
runtimeReportedBaseUrl: "",
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isStaleStoredDesktopConnection({
|
||||
desktopRuntime: true,
|
||||
desktopServerReportedNotReady: false,
|
||||
storedBaseUrl: "http://127.0.0.1:4100",
|
||||
runtimeReportedBaseUrl: "",
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
isStaleStoredDesktopConnection({
|
||||
desktopRuntime: false,
|
||||
desktopServerReportedNotReady: true,
|
||||
storedBaseUrl: "http://127.0.0.1:4100",
|
||||
runtimeReportedBaseUrl: "",
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("keeps remote URLs unless they match the runtime-reported base URL", () => {
|
||||
expect(
|
||||
isStaleStoredDesktopConnection({
|
||||
desktopRuntime: true,
|
||||
desktopServerReportedNotReady: true,
|
||||
storedBaseUrl: "https://manual.example.com",
|
||||
runtimeReportedBaseUrl: "",
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
isStaleStoredDesktopConnection({
|
||||
desktopRuntime: true,
|
||||
desktopServerReportedNotReady: true,
|
||||
storedBaseUrl: "https://manual.example.com",
|
||||
runtimeReportedBaseUrl: "https://manual.example.com",
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isStaleStoredDesktopConnection({
|
||||
desktopRuntime: true,
|
||||
desktopServerReportedNotReady: true,
|
||||
storedBaseUrl: "",
|
||||
runtimeReportedBaseUrl: "",
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user