import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; import vm from "node:vm"; import localOrigin from "./local-origin.cjs"; import environments from "./environments.cjs"; const origin = "http://127.0.0.1:48993", methods = ["state", "begin", "signInAgain", "reopen", "cancel", "refresh", "signOut", "openDashboard", "offer"]; const bridgeMethods = [...methods, "connectHome", "connectHomeForPhone"]; function preload({ enabled = true, remote = false } = {}) { let bridge; const invoked = []; vm.runInNewContext(readFileSync(new URL("./preload.cjs", import.meta.url), "utf8"), { process: { platform: "fixture", argv: [`--omb-local-origin=${origin}`, ...(enabled ? ["--omb-company-desktop=1"] : [])] }, location: { origin: remote ? "https://remote.example.test" : origin }, TextEncoder, localStorage: { getItem: () => null }, require: () => ({ webUtils: {}, contextBridge: { exposeInMainWorld: (_name, value) => { bridge = value; } }, ipcRenderer: { on() {}, removeListener() {}, send() {}, invoke: (...args) => { invoked.push(args); return Promise.resolve({ status: "signed-out" }); } } }), }); return { bridge, invoked }; } test("personal Cloud bridge is desktop-local, contains no capability access, and discards all renderer arguments", async () => { const f = preload(); for (const method of bridgeMethods) await f.bridge.cloudAccount[method]({ origin: "https://evil.example.test", paid: true, accessToken: "forged", code: "ABCD-EFGH-JKLM" }); assert.deepEqual(f.invoked, bridgeMethods.map(method => [`cloud-account:${method}`])); assert.equal(f.bridge.cloudAccount.connection, undefined); assert.equal(preload({ enabled: false }).bridge.cloudAccount, undefined); assert.equal(preload({ remote: true }).bridge.cloudAccount, undefined); }); test("production personal Cloud IPC guards exact local main frame and forwards no arguments", async () => { const source = readFileSync(new URL("./main.mjs", import.meta.url), "utf8"), start = source.indexOf("const workspaceOnly ="), end = source.indexOf('ipcMain.handle("organization:settings-opened"', start); assert.ok(start >= 0 && end > start); const handlers = new Map(), calls = [], frame = { url: `${origin}/` }, contents = { mainFrame: frame }; localOrigin.setLocalOrigin(origin); const context = vm.createContext({ ipcMain: { handle: (channel, handler) => handlers.set(channel, handler) }, localOnly: localOrigin.localOnly, workspaceSenderAllowed: environments.workspaceSenderAllowed, mainWindow: { webContents: contents }, rendererOrigin: () => origin, environmentsState: { environments: [], activeId: "local" }, ensureCloudAccount: () => Object.fromEntries(methods.map(method => [method, (...args) => { calls.push([method, ...args]); return { status: "signed-out" }; }])), connectCloudHome: (...args) => { calls.push(["connectHome", ...args]); return { status: "connected" }; }, accounts: { signOutActive: (...args) => { calls.push(["signOut", ...args]); return { status: "signed-out" }; } }, }); vm.runInContext(source.slice(start, end), context); for (const method of bridgeMethods) { const handle = handlers.get(`cloud-account:${method}`); await handle({ sender: contents, senderFrame: frame }, { paid: true }); for (const sender of [{ sender: contents, senderFrame: { url: `${origin}/subframe` } }, { sender: {}, senderFrame: frame }, { sender: contents, senderFrame: { url: "https://remote.example.test" } }, { sender: contents }]) assert.throws(() => handle(sender), /only available/); } assert.deepEqual(calls, bridgeMethods.map(method => method === "connectHomeForPhone" ? ["connectHome", "phone"] : [method])); }); test("a team's Cloud opens from the page by its id alone: the team comes from the verified session, and opens as the switcher opens it", async () => { const f = preload(); await f.bridge.cloudAccount.openTeam({ toString: () => "team-acme" }, { origin: "https://evil.example.test" }); assert.deepEqual(f.invoked, [["cloud-account:openTeam", "team-acme"]]); const source = readFileSync(new URL("./main.mjs", import.meta.url), "utf8"), start = source.indexOf("const workspaceOnly ="), end = source.indexOf('ipcMain.handle("organization:settings-opened"', start); const handlers = new Map(), shown = [], cancelled = [], frame = { url: `${origin}/` }, contents = { mainFrame: frame }; const acme = { id: "team-acme", name: "Acme", role: "member", machine: { status: "ready", origin: "https://omb-t-2.fly.dev" } }; let state = { status: "connected", teams: [acme] }; localOrigin.setLocalOrigin(origin); const context = vm.createContext({ ipcMain: { handle: (channel, handler) => handlers.set(channel, handler) }, localOnly: localOrigin.localOnly, workspaceSenderAllowed: environments.workspaceSenderAllowed, mainWindow: { webContents: contents }, rendererOrigin: () => origin, environmentsState: { environments: [], activeId: "local" }, ensureCloudAccount: () => ({ state: () => state }), homeWindow: { cancel: () => cancelled.push(1) }, showHome: async options => { shown.push(JSON.parse(JSON.stringify(options))); } }); vm.runInContext(source.slice(start, end), context); const open = handlers.get("cloud-account:openTeam"), page = { sender: contents, senderFrame: frame }; await open(page, "team-acme"); assert.deepEqual(shown, [{ place: { team: "team-acme", name: "Acme" } }]); assert.equal(cancelled.length, 1, "a team chosen from the page takes the window back from any recovery"); await assert.rejects(async () => open(page, "team-other"), /not in that team/); state = { status: "unavailable", teams: [acme] }; await assert.rejects(async () => open(page, "team-acme"), /not in that team/, "only a connected session's teams"); assert.throws(() => open({ sender: contents, senderFrame: { url: "https://remote.example.test" } }, "team-acme"), /only available/); assert.equal(shown.length, 1); }); test("a checkout from the page carries only a plan and a source, as text; the server menu only 'howto'", async () => { const f = preload(); await f.bridge.cloudAccount.checkout("pro", "app_card", { origin: "https://evil.example.test", paid: true }); await f.bridge.cloudAccount.checkout({ toString: () => "max" }, undefined); await f.bridge.workspaces.menu({ from: "howto", origin: "https://evil.example.test" }); await f.bridge.workspaces.menu({ from: "elsewhere" }); await f.bridge.workspaces.menu(); assert.deepEqual(f.invoked, [["cloud-account:checkout", "pro", "app_card"], ["cloud-account:checkout", "max", "undefined"], ["workspaces:menu", "howto"], ["workspaces:menu"], ["workspaces:menu"]]); }); test("main opens a checkout only for a plan the offer sells now and one of this app's sources, where Cloud is offered", async () => { const { CHECKOUT_SOURCES } = await import("./cloud-account.mjs"); const source = readFileSync(new URL("./main.mjs", import.meta.url), "utf8"), start = source.indexOf("const workspaceOnly ="), end = source.indexOf('ipcMain.handle("organization:settings-opened"', start); const handlers = new Map(), calls = [], frame = { url: `${origin}/` }, contents = { mainFrame: frame }; localOrigin.setLocalOrigin(origin); let allowed = true; const offer = { plans: [{ tier: "starter", amount: 1500 }, { tier: "pro", amount: 4900, trialDays: 7 }], recommended: "pro" }; const context = vm.createContext({ ipcMain: { handle: (channel, handler) => handlers.set(channel, handler) }, localOnly: localOrigin.localOnly, workspaceSenderAllowed: environments.workspaceSenderAllowed, mainWindow: { webContents: contents }, rendererOrigin: () => origin, environmentsState: { environments: [], activeId: "local" }, CHECKOUT_SOURCES, cloudOffersReady: async () => allowed, ensureCloudAccount: () => ({ offer: async () => offer, checkout: async (...args) => { calls.push(args); return { outcome: "opened", state: { status: "connected" } }; } }), connectCloudHome: () => ({ status: "connected" }), }); vm.runInContext(source.slice(start, end), context); const handle = handlers.get("cloud-account:checkout"), event = { sender: contents, senderFrame: frame }; assert.deepEqual(await handle(event, "pro", "app_card"), { outcome: "opened", state: { status: "connected" } }); assert.deepEqual(await handle(event, "pro", "app_onboarding"), { outcome: "opened", state: { status: "connected" } }, "the welcome's Cloud beat"); for (const [plan, from] of [["max", "app_card"], ["team", "app_menu"], ["pro", "site_pro"], ["pro", "cloud_page"], [{ tier: "pro" }, "app_card"], ["pro", undefined]]) { await assert.rejects(handle(event, plan, from), /Choose a plan/, `${plan} ${from}`); } assert.throws(() => handle({ sender: contents, senderFrame: { url: "https://remote.example.test/" } }, "pro", "app_card"), /only available/); allowed = false; await assert.rejects(handle(event, "pro", "app_card"), /isn't offered/); assert.deepEqual(calls, [["pro", "app_card"], ["pro", "app_onboarding"]]); }); test("Cancel and Keep my plan from Settings carry only the survey's words, and only the exact local main frame may ask", async () => { const f = preload(); await f.bridge.cloudAccount.cancelPlan({ answer: "price", expected: "words" }, { origin: "https://evil.example.test" }); await f.bridge.cloudAccount.cancelPlan(); await f.bridge.cloudAccount.keepPlan({ cloudId: "someone-elses" }); assert.deepEqual(f.invoked, [["cloud-account:cancelPlan", { answer: "price", expected: "words" }], ["cloud-account:cancelPlan", null], ["cloud-account:keepPlan"]]); const source = readFileSync(new URL("./main.mjs", import.meta.url), "utf8"), start = source.indexOf("const workspaceOnly ="), end = source.indexOf('ipcMain.handle("organization:settings-opened"', start); const handlers = new Map(), calls = [], frame = { url: `${origin}/` }, contents = { mainFrame: frame }; localOrigin.setLocalOrigin(origin); const context = vm.createContext({ ipcMain: { handle: (channel, handler) => handlers.set(channel, handler) }, localOnly: localOrigin.localOnly, workspaceSenderAllowed: environments.workspaceSenderAllowed, mainWindow: { webContents: contents }, rendererOrigin: () => origin, environmentsState: { environments: [], activeId: "local" }, ensureCloudAccount: () => ({ cancelPlan: (...args) => { calls.push(["cancelPlan", ...args]); return { outcome: "cancelled" }; }, keepPlan: (...args) => { calls.push(["keepPlan", ...args]); return { outcome: "kept" }; } }) }); vm.runInContext(source.slice(start, end), context); const page = { sender: contents, senderFrame: frame }; await handlers.get("cloud-account:cancelPlan")(page, { answer: "setup" }, "https://evil.example.test"); await handlers.get("cloud-account:keepPlan")(page, "anything"); assert.deepEqual(calls, [["cancelPlan", { answer: "setup" }], ["keepPlan"]]); for (const channel of ["cloud-account:cancelPlan", "cloud-account:keepPlan"]) { for (const sender of [{ sender: contents, senderFrame: { url: `${origin}/subframe` } }, { sender: {}, senderFrame: frame }, { sender: contents, senderFrame: { url: "https://remote.example.test" } }]) assert.throws(() => handlers.get(channel)(sender, { answer: "price" }), /only available/); } assert.equal(calls.length, 2); });