electron/cloud-connections.node-test.mjs
Rama main · réplica de lectura del repositorio original.
import assert from "node:assert/strict";
import test from "node:test";
import { adoptComposioId, collectConnections, ConnectionMoveError, parseConnections, releaseConnections, sendConnections } from "./cloud-connections.mjs";
const COMPUTER = { environmentId: "env-desktop-1", label: "Milind's MacBook" };
const INSTALLATION = "0f1e2d3c-4b5a-4968-8778-695a4b3c2d1e";
const D1 = "1".repeat(64), D2 = "2".repeat(64);
const linearSignIn = (refresh) => ({ url: "https://mcp.linear.app/sse", state: "signed-in", tokens: { access: `a-${refresh}`, refresh } });
/** This computer's server: its list, and the private port's answers, each ask recorded. */
function computer({ connections, answers = {}, release = () => ({ released: true }), connected = {} }) {
const asked = [];
return {
asked,
json: async (route) => (route === "/api/cloud-connections" ? { computer: COMPUTER, connections, engines: [], commands: [] } : { services: connected }),
handoff: async (what) => {
asked.push(what);
if (what.kind === "connection-release") return { ok: true, release: release(what) };
if (what.kind === "composio-share") return { ok: true, share: { code: "c".repeat(64) } };
const answer = typeof answers[what.id] === "function" ? answers[what.id]() : answers[what.id];
if (!answer) throw new Error("This connection could not be read on this computer.");
return { ok: true, ...answer };
},
};
}
/** My Cloud's own routes over the owner session, each call recorded; `reply` answers anything not set up here. */
function cloud({ connections = [], engines = [], commands = ["npx", "node"], reply = () => ({ status: 200, body: {} }), readyAfter = 0, vaultKeys = false } = {}) {
const calls = [];
let reads = 0;
return {
calls,
call: async (method, route, body) => {
calls.push([method, route, body]);
if (method === "GET" && route === "/api/cloud-connections") {
reads++;
return { ok: true, status: 200, body: { computer: { environmentId: "env-cloud", label: "omb-u-1" }, connections, engines: reads > readyAfter ? engines : [], commands, ...(vaultKeys ? { vaultKeys } : {}) } };
}
const answer = reply(method, route, body) ?? { status: 200, body: {} };
return { ok: answer.status >= 200 && answer.status < 300, ...answer };
},
};
}
const writes = (target) => target.calls.filter(([method]) => method !== "GET").map(([method, route]) => `${method} ${route}`);
test("moves keys first, then MCP servers with their secrets, mailboxes and connected apps, each over My Cloud's own routes", async () => {
const local = computer({
connections: [
{ id: "mcp:dodo", kind: "mcp", label: "dodo", launcher: "npx" },
{ id: "composio", kind: "composio", label: "Connected apps", mode: "managed", account: "managed:aaa" },
{ id: "email", kind: "email", label: "Email" },
{ id: "key:openrouter", kind: "key", label: "OpenRouter", for: ["openrouter"] },
],
answers: {
"mcp:dodo": { connection: { mcp: { name: "dodo", server: { command: "npx", args: ["-y", "dodo"], env: { KEY: "k" }, enabled: true } } } },
email: { connection: { email: [{ address: "ana@example.test" }] } },
"key:openrouter": { connection: { config: { openrouter: { key: "sk-or" } } } },
},
connected: { gmail: { connected: true }, slack: { connected: false } },
});
const target = cloud({ connections: [{ id: "composio", kind: "composio", label: "Connected apps", mode: "managed", account: "managed:bbb", installationId: INSTALLATION }],
engines: ["openrouter"], reply: (method, route) => (route === "/api/cloud-connections/connected-apps" ? { status: 200, body: { shared: true } } : undefined) });
const progress = [];
const result = await sendConnections(await collectConnections(local), target, { local, onProgress: (step) => progress.push(step) });
assert.deepEqual(result.failed, []);
assert.deepEqual(writes(target), ["PUT /api/cloud-connections/held-keys", "PATCH /api/config", "POST /api/mcp/servers", "PATCH /api/mcp/servers/dodo", "PUT /api/cloud-connections/email", "POST /api/cloud-connections/connected-apps"]);
assert.deepEqual(result.held, [], "a Cloud with no trial credit to keep runs the key at once");
assert.deepEqual(target.calls.find(([, route]) => route === "/api/mcp/servers")[2], { name: "dodo", command: "npx", args: ["-y", "dodo"], env: { KEY: "k" } });
assert.deepEqual(target.calls.find(([, route]) => route === "/api/cloud-connections/connected-apps")[2], { share: "c".repeat(64), apps: ["gmail"] });
assert.deepEqual(local.asked.find((what) => what.kind === "composio-share"), { kind: "composio-share", for: INSTALLATION });
assert.deepEqual(target.calls.find(([, route]) => route === "/api/cloud-connections/email")[2], { accounts: [{ address: "ana@example.test" }] });
assert.deepEqual(result.moved.map((item) => item.id), ["key:openrouter", "mcp:dodo", "email", "composio"]);
assert.deepEqual(progress.map((step) => `${step.done}/${step.total} ${step.label}`), ["1/4 OpenRouter", "2/4 dodo", "3/4 Email", "4/4 Connected apps"]);
});
test("a trial's Cloud keeps a moved key saved but unused while its Claude credit lasts, asked before the key is saved, and the move goes on without waiting for it", async () => {
const local = computer({
connections: [{ id: "key:openrouter", kind: "key", label: "OpenRouter", for: ["openrouter"] }, { id: "mcp:dodo", kind: "mcp", label: "dodo", launcher: "npx" }],
answers: {
"key:openrouter": { connection: { config: { openrouter: { key: "sk-or" } } } },
"mcp:dodo": { connection: { mcp: { name: "dodo", server: { command: "npx", args: ["-y", "dodo"], env: {}, enabled: true } } } },
},
});
const target = cloud({ engines: [], reply: (method, route) => (route === "/api/cloud-connections/held-keys" ? { status: 200, body: { held: true } } : undefined) });
const started = Date.now();
const result = await sendConnections(await collectConnections(local), target, { local, waitMs: 5_000 });
assert.ok(Date.now() - started < 2_000, "an engine kept unused is never waited for");
assert.deepEqual(writes(target).slice(0, 2), ["PUT /api/cloud-connections/held-keys", "PATCH /api/config"]);
assert.deepEqual(target.calls.find(([, route]) => route === "/api/cloud-connections/held-keys")[2], { for: ["openrouter"] });
assert.deepEqual(result.held, [{ id: "key:openrouter", label: "OpenRouter" }]);
assert.deepEqual(result.moved.map((item) => item.id), ["key:openrouter", "mcp:dodo"]);
});
test("a server that needs this computer goes marked as running on it, and a server already on My Cloud is replaced", async () => {
const server = (name, extra = {}) => ({ connection: { mcp: { name, server: { type: "http", url: `https://${name}.example/mcp`, headers: {}, enabled: true, ...extra } } } });
const local = computer({
connections: [
{ id: "mcp:notes", kind: "mcp", label: "notes", runsHere: true },
{ id: "mcp:fetch", kind: "mcp", label: "fetch", launcher: "uvx" },
{ id: "mcp:lent", kind: "mcp", label: "lent" },
{ id: "mcp:docs", kind: "mcp", label: "docs" },
],
answers: {
"mcp:notes": server("notes"),
"mcp:fetch": { connection: { mcp: { name: "fetch", server: { command: "uvx", args: ["mcp-server-fetch"], env: {}, enabled: false } } } },
"mcp:lent": server("lent", { runsOn: { environmentId: "env-other", label: "Studio iMac" } }),
"mcp:docs": server("docs"),
},
});
const target = cloud({ connections: [{ id: "mcp:docs", kind: "mcp", label: "docs" }] });
const result = await sendConnections(await collectConnections(local), target, { local });
const body = (route) => target.calls.find(([, at]) => at === route)?.[2];
const added = target.calls.filter(([method, route]) => method === "POST" && route === "/api/mcp/servers").map(([, , sent]) => [sent.name, sent.runsOn ?? null]);
assert.deepEqual(added, [["notes", COMPUTER], ["fetch", COMPUTER], ["lent", { environmentId: "env-other", label: "Studio iMac" }]]);
assert.deepEqual(body("/api/mcp/servers/docs"), { type: "http", url: "https://docs.example/mcp", headers: {}, enabled: true, runsOn: null });
assert.equal(target.calls.some(([method, route]) => method === "PATCH" && route === "/api/mcp/servers/fetch"), false, "a server switched off here stays off there");
assert.deepEqual(result.runsHere, [{ id: "mcp:notes", label: "notes" }, { id: "mcp:fetch", label: "fetch", needs: "uvx", off: true }, { id: "mcp:lent", label: "lent" }]);
assert.deepEqual(result.moved.map((item) => item.id), ["mcp:docs"]);
});
test("a server's Vault keys go with it as pointers, and only to a Cloud that can read them", async () => {
const item = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa";
const connections = [{ id: "mcp:stripe", kind: "mcp", label: "stripe", launcher: "npx" }];
const answers = { "mcp:stripe": { connection: { mcp: { name: "stripe", server: { command: "npx", args: ["x"], env: { KEY: `vault:${item}` }, enabled: false }, keys: [item] } } } };
const here = computer({ connections, answers });
const collected = await collectConnections(here);
const newer = cloud({ vaultKeys: true });
assert.deepEqual((await sendConnections(collected, newer, { local: here, waitMs: 0 })).failed, []);
const added = newer.calls.find(([method, route]) => method === "POST" && route === "/api/mcp/servers");
assert.deepEqual(added[2].vaultKeys, [item]);
assert.equal(added[2].env.KEY, `vault:${item}`);
const older = cloud({});
const stayed = await sendConnections(collected, older, { local: here, waitMs: 0 });
assert.equal(stayed.failed.length, 1);
assert.match(stayed.failed[0].message, /update/u);
assert.equal(stayed.failed[0].final, false);
assert.deepEqual(writes(older), []);
});
test("a sign-in moves and this computer lets go of it; one that refreshed meanwhile goes again first", async () => {
let refresh = "r1";
const local = computer({
connections: [{ id: "mcp:linear", kind: "mcp", label: "linear", signIn: true }],
answers: { "mcp:linear": () => ({ connection: { mcp: { name: "linear", server: { type: "http", url: "https://mcp.linear.app/sse", headers: {}, enabled: true }, signIn: linearSignIn(refresh) } },
digest: refresh === "r1" ? D1 : D2 }) },
release: (what) => (what.digest === (refresh === "r1" ? D1 : D2) ? { released: true } : { changed: true }),
});
const target = cloud({ reply: (method, route) => (route.startsWith("/api/cloud-connections/mcp/linear/sign-in") ? { status: 200, body: { adopted: true } } : undefined) });
// It refreshed here between being read and being let go of.
const read = local.handoff;
local.handoff = async (what) => { const answer = await read(what); if (what.kind === "connection" && refresh === "r1") refresh = "r2"; return answer; };
const result = await sendConnections(await collectConnections(local), target, { local });
assert.deepEqual(result.failed, []);
assert.deepEqual(writes(target), ["POST /api/mcp/servers", "PATCH /api/mcp/servers/linear", "PUT /api/cloud-connections/mcp/linear/sign-in",
`PUT /api/cloud-connections/mcp/linear/sign-in?replaces=${D1}`]);
assert.equal(target.calls.at(-1)[2].tokens.refresh, "r2");
assert.deepEqual(local.asked.filter((what) => what.kind === "connection-release"), [
{ kind: "connection-release", id: "mcp:linear", digest: D1 }, { kind: "connection-release", id: "mcp:linear", digest: D2 }]);
assert.deepEqual(result.release, []);
});
test("My Cloud keeps a sign-in of its own; with release off the result lists what this computer still holds, for later", async () => {
const connections = [{ id: "mcp:linear", kind: "mcp", label: "linear", signIn: true }];
const answers = {
"mcp:linear": { connection: { mcp: { name: "linear", server: { type: "http", url: "https://mcp.linear.app/sse", headers: {}, enabled: true }, signIn: linearSignIn("r1") } }, digest: D1 },
};
const keeps = computer({ connections, answers });
const own = cloud({ connections: [{ id: "mcp:linear", kind: "mcp", label: "linear" }], reply: (method, route) => (route.includes("sign-in") ? { status: 200, body: { kept: true } } : undefined) });
const kept = await sendConnections(await collectConnections(keeps), own, { local: keeps });
assert.deepEqual(kept.kept.map((item) => item.id), ["mcp:linear"]);
assert.deepEqual(kept.moved.map((item) => item.id), ["mcp:linear"], "its definition went; its sign-in there is its own");
assert.equal(keeps.asked.some((what) => what.kind === "connection-release"), false);
const holds = computer({ connections, answers });
const takes = cloud({ reply: (method, route) => (route.includes("sign-in") ? { status: 200, body: { adopted: true } } : undefined) });
const held = await sendConnections(await collectConnections(holds), takes, { local: holds, release: false });
assert.deepEqual(held.release, [{ id: "mcp:linear", label: "linear", digest: D1 }]);
assert.equal(holds.asked.some((what) => what.kind === "connection-release"), false);
// A held entry of a connection kind this app does not know is dropped, never asked about.
assert.deepEqual(await releaseConnections([...held.release, { id: "highlevel", label: "HighLevel", digest: D2 }], { local: holds, target: takes }), []);
assert.deepEqual(holds.asked.filter((what) => what.kind === "connection-release").map((what) => what.id), ["mcp:linear"]);
});
test("one connection failing never stops the others; a refusal trying again can't fix is final", async () => {
const local = computer({
connections: [{ id: "key:openai", kind: "key", label: "OpenAI", for: ["openai"] }, { id: "key:groq", kind: "key", label: "Groq", for: ["groq"] },
{ id: "mcp:gone", kind: "mcp", label: "gone" }, { id: "mcp:docs", kind: "mcp", label: "docs" }],
answers: { "key:openai": { connection: { config: { openai: { key: "k" } } } }, "key:groq": { connection: { config: { groq: { key: "g" } } } },
"mcp:docs": { connection: { mcp: { name: "docs", server: { type: "http", url: "https://docs.example/mcp", headers: {}, enabled: true } } } } },
});
let config = 0;
const target = cloud({ reply: (method, route) => {
if (route === "/api/config") return ++config === 1 ? { status: 403, body: { error: "This workspace's AI is managed by its organization." } } : { status: 503, body: {} };
return undefined;
} });
const result = await sendConnections(await collectConnections(local), target, { local, waitMs: 0 });
assert.deepEqual(result.failed, [
{ id: "key:openai", label: "OpenAI", message: "My Cloud said: This workspace's AI is managed by its organization.", final: true },
{ id: "key:groq", label: "Groq", message: "My Cloud did not take the Groq key.", final: false },
{ id: "mcp:gone", label: "gone", message: "gone could not be read on this computer.", final: false },
]);
assert.deepEqual(result.moved.map((item) => item.id), ["mcp:docs"]);
});
test("waits for My Cloud to run the engines whose keys went, before anything that follows them", async () => {
const local = computer({ connections: [{ id: "key:openrouter", kind: "key", label: "OpenRouter", for: ["openrouter"] }, { id: "mcp:docs", kind: "mcp", label: "docs" }],
answers: { "key:openrouter": { connection: { config: { openrouter: { key: "k" } } } },
"mcp:docs": { connection: { mcp: { name: "docs", server: { type: "http", url: "https://docs.example/mcp", headers: {}, enabled: false } } } } } });
const target = cloud({ engines: ["openrouter"], readyAfter: 2 });
await sendConnections(await collectConnections(local), target, { local, waitMs: 5_000 });
const order = target.calls.map(([method, route]) => `${method} ${route}`);
const ready = order.lastIndexOf("GET /api/cloud-connections");
assert.ok(ready > order.indexOf("PATCH /api/config") && ready < order.indexOf("POST /api/mcp/servers"), order.join(", "));
assert.equal(order.filter((call) => call === "GET /api/cloud-connections").length, 3);
});
test("connected apps: the same account already, the person's own project, a Cloud not ready, and one that keeps its own", async () => {
const here = { id: "composio", kind: "composio", label: "Connected apps", mode: "managed", account: "managed:aaa" };
const local = computer({ connections: [], answers: { composio: { connection: { composio: { apiKey: "ck", userId: "u1" } } } }, connected: { gmail: { connected: true } } });
const quiet = cloud();
assert.deepEqual(await adoptComposioId(quiet, { local, here, there: { ...here, installationId: INSTALLATION } }), { shared: true });
assert.deepEqual(quiet.calls, []);
await assert.rejects(adoptComposioId(quiet, { local, here, there: null }), (error) => error instanceof ConnectionMoveError && error.code === "not_ready" && !error.final);
const keeps = cloud({ reply: () => ({ status: 200, body: { kept: true, missing: ["gmail", "BAD SLUG"] } }) });
assert.deepEqual(await adoptComposioId(keeps, { local, here: { ...here, mode: "own", account: "own:x" }, there: null }), { kept: true, missing: ["gmail"] });
assert.deepEqual(keeps.calls[0], ["POST", "/api/cloud-connections/connected-apps", { apiKey: "ck", userId: "u1", apps: ["gmail"] }]);
});
test("a server of the person's own with no connected-apps service keeps MausBot's connected apps here for good, and still takes their own project", async () => {
const here = { id: "composio", kind: "composio", label: "Connected apps", mode: "managed", account: "managed:aaa" };
const local = computer({ connections: [here], answers: { composio: { connection: { composio: { apiKey: "ck", userId: "u1" } } } }, connected: { gmail: { connected: true } } });
assert.deepEqual(parseConnections({ computer: COMPUTER, connections: [], managedApps: false }).managedApps, false);
assert.equal(parseConnections({ computer: COMPUTER, connections: [] }).managedApps, undefined, "an Admin's Cloud says nothing: as before");
const garage = cloud();
await assert.rejects(adoptComposioId(garage, { local, here, there: null, managedApps: false }), (error) => error.code === "no_service" && error.final === true);
assert.deepEqual(garage.calls, [], "nothing asked of it");
const listing = { status: 200, body: { computer: { environmentId: "env-garage", label: "Garage server" }, connections: [], engines: [], commands: [], managedApps: false } };
const moved = await sendConnections({ computer: COMPUTER, connections: [here] }, { call: async (method, route) => (method === "GET" && route === "/api/cloud-connections" ? { ok: true, ...listing } : { ok: true, status: 200, body: {} }) }, { local, waitMs: 0 });
assert.deepEqual(moved.failed.map((failure) => [failure.id, failure.final]), [["composio", true]], "final: the move's check leaves it out");
const own = cloud({ reply: () => ({ status: 200, body: { shared: true } }) });
assert.deepEqual(await adoptComposioId(own, { local, here: { ...here, mode: "own", account: "own:x" }, there: null, managedApps: false }), { shared: true });
});
test("a Cloud too old for connections says so; one that does not answer, too; this computer must list its own", async () => {
const local = computer({ connections: [] });
const old = { call: async () => ({ ok: false, status: 404, body: {} }) };
await assert.rejects(sendConnections({ computer: COMPUTER, connections: [] }, old, { local }), (error) => error.code === "outdated");
const down = { call: async () => { throw new Error("offline"); } };
await assert.rejects(sendConnections({ computer: COMPUTER, connections: [] }, down, { local }), (error) => error.code === "unreachable");
await assert.rejects(collectConnections({ json: async () => ({ nope: true }) }), (error) => error.code === "local");
});
test("a server's list keeps only connections of the known shape", () => {
const parsed = parseConnections({ computer: COMPUTER, engines: ["openrouter", "bad engine!"], commands: ["npx", "rm -rf"], connections: [
{ id: "mcp:dodo", kind: "mcp", label: "dodo", launcher: "npx", runsHere: true, extra: "x" },
{ id: "mcp:dodo", kind: "key", label: "mismatched kind" },
{ id: "../etc", kind: "mcp", label: "bad id" },
{ id: "composio", kind: "composio", label: "Connected apps", mode: "managed", account: "managed:a", installationId: "not-a-uuid" },
] });
assert.deepEqual(parsed, { computer: COMPUTER, engines: ["openrouter"], commands: ["npx"], connections: [
{ id: "mcp:dodo", kind: "mcp", label: "dodo", runsHere: true, launcher: "npx" },
{ id: "composio", kind: "composio", label: "Connected apps", mode: "managed", account: "managed:a" },
] });
assert.equal(parseConnections({ computer: { environmentId: "../x", label: "Mac" }, connections: [] }), null);
});