import { describe, expect, it } from "@effect/vitest";import { Effect, Exit } from "effect"; import { buildBridge, resolveIntegrationBindings, type ClientResolver } from "./bindings";import type { IntegrationDecl } from "../pipeline/descriptor"; // ---------------------------------------------------------------------------// Strict HandleBridge dispatch (Fix 4, grafted from build A). The bridge is the// ONE channel out of the sandbox, so its dispatch must reject anything// malformed, reserved, undeclared, or out-of-range rather than resolve it.// --------------------------------------------------------------------------- const okResolver: ClientResolver = { listConnections: ({ integration }) => Effect.succeed([ { address: `tools.${integration}.user.main`, integration, name: "main", owner: "user", }, ]), resolveConnection: ({ connection }) => Effect.succeed( connection === "tools.github.user.main" ? { address: "tools.github.user.main", integration: "github", name: "main", owner: "user", } : null, ), call: () => Effect.succeed({ ok: true }),}; const fails = <A, E>(effect: Effect.Effect<A, E>): Promise<boolean> => Effect.runPromiseExit(effect).then((exit) => Exit.isFailure(exit)); const failureText = <A, E>(effect: Effect.Effect<A, E>): Promise<string> => Effect.runPromiseExit(effect).then((exit) => JSON.stringify(exit)); describe("HandleBridge strict dispatch", () => { const declared: Record<string, IntegrationDecl> = { gh: { integration: "github" }, }; const bindings = { gh: "tools.github.user.main", }; const bridge = buildBridge({ declared, bindings, resolver: okResolver }); it("rejects an empty method path", async () => { expect(await fails(bridge.call({ root: "gh", path: [], args: [] }))).toBe(true); }); it("rejects a reserved root", async () => { expect(await fails(bridge.call({ root: "__proto__", path: ["x"], args: [] }))).toBe(true); }); it("rejects an undeclared root", async () => { expect(await fails(bridge.call({ root: "ghost", path: ["x"], args: [] }))).toBe(true); }); it("rejects an index on an integration role", async () => { expect(await fails(bridge.call({ root: "gh#0", path: ["repos", "list"], args: [] }))).toBe( true, ); }); it("routes a valid single-connection call through the resolver", async () => { const out = await Effect.runPromise( bridge.call({ root: "gh", path: ["repos", "list"], args: [{}] }), ); expect(out).toEqual({ ok: true }); }); it("defaults a missing role property when exactly one connection exists", async () => { const resolved = await Effect.runPromise(resolveIntegrationBindings(declared, {}, okResolver)); expect(resolved.bindings).toEqual({ gh: "tools.github.user.main" }); expect(resolved.input).toEqual({}); }); it("fails when several connections exist and the role property is missing", async () => { const resolver: ClientResolver = { ...okResolver, listConnections: () => Effect.succeed([ { address: "tools.github.user.one", integration: "github" }, { address: "tools.github.user.two", integration: "github" }, ]), }; expect(await fails(resolveIntegrationBindings(declared, {}, resolver))).toBe(true); }); it("fails when a requested connection belongs to a different integration", async () => { const resolver: ClientResolver = { ...okResolver, resolveConnection: () => Effect.succeed({ address: "tools.gmail.user.main", integration: "gmail" }), }; expect( await fails(resolveIntegrationBindings(declared, { gh: "tools.gmail.user.main" }, resolver)), ).toBe(true); }); it("fails when a requested connection is unknown", async () => { expect( await fails( resolveIntegrationBindings(declared, { gh: "tools.github.user.missing" }, okResolver), ), ).toBe(true); }); it("rejects a bare connection name and lists valid addresses", async () => { const text = await failureText( resolveIntegrationBindings(declared, { gh: "main" }, okResolver), ); expect(text).toContain('"message"'); expect(text).toContain("unknown connection"); expect(text).toContain("for role"); expect(text).toContain('"requestedConnection":"main"'); expect(text).toContain("tools.github.user.main"); expect(text).not.toContain("unambiguous connection name"); });});
import { describe, expect, it } from "@effect/vitest";
import { Effect, Exit } from "effect";
import { buildBridge, resolveIntegrationBindings, type ClientResolver } from "./bindings";
import type { IntegrationDecl } from "../pipeline/descriptor";
// ---------------------------------------------------------------------------
// Strict HandleBridge dispatch (Fix 4, grafted from build A). The bridge is the
// ONE channel out of the sandbox, so its dispatch must reject anything
// malformed, reserved, undeclared, or out-of-range rather than resolve it.
// ---------------------------------------------------------------------------
const okResolver: ClientResolver = {
listConnections: ({ integration }) =>
Effect.succeed([
{
address: `tools.${integration}.user.main`,
integration,
name: "main",
owner: "user",
},
]),
resolveConnection: ({ connection }) =>
Effect.succeed(
connection === "tools.github.user.main"
? {
address: "tools.github.user.main",
integration: "github",
name: "main",
owner: "user",
}
: null,
),
call: () => Effect.succeed({ ok: true }),
};
const fails = <A, E>(effect: Effect.Effect<A, E>): Promise<boolean> =>
Effect.runPromiseExit(effect).then((exit) => Exit.isFailure(exit));
const failureText = <A, E>(effect: Effect.Effect<A, E>): Promise<string> =>
Effect.runPromiseExit(effect).then((exit) => JSON.stringify(exit));
describe("HandleBridge strict dispatch", () => {
const declared: Record<string, IntegrationDecl> = {
gh: { integration: "github" },
};
const bindings = {
gh: "tools.github.user.main",
};
const bridge = buildBridge({ declared, bindings, resolver: okResolver });
it("rejects an empty method path", async () => {
expect(await fails(bridge.call({ root: "gh", path: [], args: [] }))).toBe(true);
});
it("rejects a reserved root", async () => {
expect(await fails(bridge.call({ root: "__proto__", path: ["x"], args: [] }))).toBe(true);
});
it("rejects an undeclared root", async () => {
expect(await fails(bridge.call({ root: "ghost", path: ["x"], args: [] }))).toBe(true);
});
it("rejects an index on an integration role", async () => {
expect(await fails(bridge.call({ root: "gh#0", path: ["repos", "list"], args: [] }))).toBe(
true,
);
});
it("routes a valid single-connection call through the resolver", async () => {
const out = await Effect.runPromise(
bridge.call({ root: "gh", path: ["repos", "list"], args: [{}] }),
);
expect(out).toEqual({ ok: true });
});
it("defaults a missing role property when exactly one connection exists", async () => {
const resolved = await Effect.runPromise(resolveIntegrationBindings(declared, {}, okResolver));
expect(resolved.bindings).toEqual({ gh: "tools.github.user.main" });
expect(resolved.input).toEqual({});
});
it("fails when several connections exist and the role property is missing", async () => {
const resolver: ClientResolver = {
...okResolver,
listConnections: () =>
Effect.succeed([
{ address: "tools.github.user.one", integration: "github" },
{ address: "tools.github.user.two", integration: "github" },
]),
};
expect(await fails(resolveIntegrationBindings(declared, {}, resolver))).toBe(true);
});
it("fails when a requested connection belongs to a different integration", async () => {
const resolver: ClientResolver = {
...okResolver,
resolveConnection: () =>
Effect.succeed({ address: "tools.gmail.user.main", integration: "gmail" }),
};
expect(
await fails(resolveIntegrationBindings(declared, { gh: "tools.gmail.user.main" }, resolver)),
).toBe(true);
});
it("fails when a requested connection is unknown", async () => {
expect(
await fails(
resolveIntegrationBindings(declared, { gh: "tools.github.user.missing" }, okResolver),
),
).toBe(true);
});
it("rejects a bare connection name and lists valid addresses", async () => {
const text = await failureText(
resolveIntegrationBindings(declared, { gh: "main" }, okResolver),
);
expect(text).toContain('"message"');
expect(text).toContain("unknown connection");
expect(text).toContain("for role");
expect(text).toContain('"requestedConnection":"main"');
expect(text).toContain("tools.github.user.main");
expect(text).not.toContain("unambiguous connection name");
});
});