import { describe, expect, it } from "@effect/vitest";import { Cause, Deferred, Effect, Exit, Fiber, Inspectable, Logger, Option, Predicate, Result, Schema, Tracer,} from "effect"; import { AuthTemplateSlug, ConnectionName, IntegrationSlug, ProviderItemId, ProviderKey, Subject, Tenant, ToolAddress, ToolName,} from "./ids";import { ConnectionAlreadyExistsError } from "./errors";import { createExecutor } from "./executor";import { StorageError, type FumaDb } from "./fuma-runtime";import { HealthCheckResult } from "./health-check";import { definePlugin, type ResolveToolsResult } from "./plugin";import type { CredentialProvider } from "./provider";import { makeTestConfig, makeTestExecutor } from "./testing";import { ToolResult } from "./tool-result"; // removed: v1 connection-refresh lifecycle, ConnectionProvider.refresh,// SecretProvider, accessToken token-refresh + in-flight dedup tests — the v2// model folds secret/connection into one provider-resolved Connection, and OAuth// refresh is core's responsibility (stubbed for milestone 1). The cases below// cover the v2 connection surface: create (inline + external), list, get,// remove, refresh, and per-connection tool production. const memoryProvider = (): CredentialProvider => { const store = new Map<string, string>(); return { key: ProviderKey.make("memory"), writable: true, get: (id) => Effect.sync(() => store.get(String(id)) ?? null), set: (id, value) => Effect.sync(() => void store.set(String(id), value)), has: (id) => Effect.sync(() => store.has(String(id))), list: () => Effect.sync(() => Array.from(store.keys()).map((key) => ({ id: ProviderItemId.make(key), name: key, })), ), };}; const INTEG = IntegrationSlug.make("vercel");const TEMPLATE = AuthTemplateSlug.make("apiKey"); /** Wrap a test `FumaDb` so every transaction it opens is observable. The * executor re-binds its own owner context onto the handle it is given, so the * wrapper must forward `withContext` re-wrapped — otherwise the instrument is * dropped before any executor query runs. */const instrumentTransactions = ( db: FumaDb, hooks: { readonly enter: () => void; readonly exit: () => void },): FumaDb => { const wrap = (inner: FumaDb): FumaDb => new Proxy(inner, { get(target, prop) { if (prop === "withContext") { return (context: unknown) => wrap((target.withContext as (c: unknown) => FumaDb)(context)); } if (prop === "transaction") { return async (run: Parameters<FumaDb["transaction"]>[0]) => { hooks.enter(); // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: test instrument must unwind on both outcomes try { return await target.transaction(run); } finally { hooks.exit(); } }; } return Reflect.get(target, prop); }, }); return wrap(db);}; const ConnectionListHealthOutput = Schema.Struct({ connections: Schema.Array(Schema.Struct({ lastHealth: Schema.NullOr(HealthCheckResult) })),});const decodeConnectionListHealthOutput = Schema.decodeUnknownEffect(ConnectionListHealthOutput); const demoPlugin = definePlugin(() => ({ id: "demo" as const, credentialProviders: [memoryProvider()], storage: () => ({}), resolveTools: () => Effect.succeed({ tools: [ { name: ToolName.make("deploy"), description: "deploy" }, { name: ToolName.make("list"), description: "list" }, ], }), invokeTool: ({ toolRow, credential }) => Effect.succeed({ ran: toolRow.name, value: credential.value }), extension: (ctx) => ({ seed: () => ctx.core.integrations.register({ slug: INTEG, description: "Vercel", config: {}, }), resolveValue: (owner: "org" | "user", name: string) => ctx.connections.resolveValue({ owner, integration: INTEG, name: ConnectionName.make(name), }), }),}))(); const setup = () => makeTestExecutor({ plugins: [demoPlugin] as const }).pipe( Effect.tap((executor) => executor.demo.seed()), ); describe("connections.create", () => { it.effect("inline value writes to the default writable provider and produces tools", () => Effect.gen(function* () { const executor = yield* setup(); const connection = yield* executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "secret-token", }); expect(connection.provider).toBe(ProviderKey.make("memory")); expect(String(connection.address)).toBe("tools.vercel.org.main"); const tools = yield* executor.tools.list(); expect(tools.map((t) => String(t.name)).sort()).toEqual(["deploy", "list"]); // The inline value is resolvable via the connection's provider. const value = yield* executor.demo.resolveValue("org", "main"); expect(value).toBe("secret-token"); }), ); it.effect("normalizes free-form names into JS-callable connection identifiers", () => Effect.gen(function* () { const executor = yield* setup(); const connection = yield* executor.connections.create({ owner: "org", name: ConnectionName.make("my-api-key"), integration: INTEG, template: TEMPLATE, value: "secret-token", }); expect(String(connection.name)).toBe("myApiKey"); expect(String(connection.address)).toBe("tools.vercel.org.myApiKey"); const tools = yield* executor.tools.list(); expect(tools.map((t) => String(t.address)).sort()).toEqual([ "tools.vercel.org.myApiKey.deploy", "tools.vercel.org.myApiKey.list", ]); const value = yield* executor.demo.resolveValue("org", "myApiKey"); expect(value).toBe("secret-token"); }), ); // Create is never a replace: a second create with the same (owner, // integration, name) must fail with ConnectionAlreadyExistsError and leave // the first connection fully intact — including its stored secret, which a // silent upsert would overwrite (the pasted value's item id is derived from // the name, so the provider write alone clobbers it). it.effect("rejects a duplicate (owner, integration, name) and keeps the original intact", () => Effect.gen(function* () { const executor = yield* setup(); yield* executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "original-token", description: "original", }); const result = yield* Effect.result( executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "clobbered-token", description: "clobbered", }), ); expect(Result.isFailure(result)).toBe(true); if (!Result.isFailure(result)) return; expect(Predicate.isTagged("ConnectionAlreadyExistsError")(result.failure)).toBe(true); // The original row and its secret both survived. const connections = yield* executor.connections.list(); expect(connections.length).toBe(1); expect(connections[0]?.description).toBe("original"); const value = yield* executor.demo.resolveValue("org", "main"); expect(value).toBe("original-token"); }), ); // Names collide AFTER identifier normalization: "my-api-key" and "my api key" // both normalize to myApiKey, so the second must be rejected even though the // raw inputs differ. it.effect("rejects a duplicate that only collides after name normalization", () => Effect.gen(function* () { const executor = yield* setup(); yield* executor.connections.create({ owner: "org", name: ConnectionName.make("my-api-key"), integration: INTEG, template: TEMPLATE, value: "v1", }); const result = yield* Effect.result( executor.connections.create({ owner: "org", name: ConnectionName.make("my api key"), integration: INTEG, template: TEMPLATE, value: "v2", }), ); expect(Result.isFailure(result)).toBe(true); if (!Result.isFailure(result)) return; expect(Predicate.isTagged("ConnectionAlreadyExistsError")(result.failure)).toBe(true); const value = yield* executor.demo.resolveValue("org", "myApiKey"); expect(value).toBe("v1"); }), ); // The race the early duplicate check cannot answer: two creates for the same // (owner, integration, name) in flight at once. The row insert picks the // winner and the loser gets the typed 409 — and, the load-bearing part, the // provider write is winner-only. A pasted value's item id is deterministic, // so a pre-insert write from the LOSING create would silently replace the // winner's stored secret while the winner's row keeps resolving through it. // The gate parks the first create inside its provider write, so the second // create runs its full duplicate handling while the first is mid-flight. it.effect("concurrent creates: one winner, a typed 409, and the winner's secret intact", () => Effect.scoped( Effect.gen(function* () { const firstWriteEntered = yield* Deferred.make<void>(); const releaseFirstWrite = yield* Deferred.make<void>(); const store = new Map<string, string>(); let writes = 0; const gatedProvider: CredentialProvider = { key: ProviderKey.make("memory"), writable: true, get: (id) => Effect.sync(() => store.get(String(id)) ?? null), set: (id, value) => Effect.gen(function* () { writes += 1; if (writes === 1) { yield* Deferred.succeed(firstWriteEntered, undefined); yield* Deferred.await(releaseFirstWrite); } store.set(String(id), value); }), }; const gatedPlugin = definePlugin(() => ({ id: "gated" as const, credentialProviders: [gatedProvider], storage: () => ({}), resolveTools: () => Effect.succeed({ tools: [{ name: ToolName.make("deploy"), description: "deploy" }], }), invokeTool: ({ toolRow }) => Effect.succeed({ ran: toolRow.name }), extension: (ctx) => ({ seed: () => ctx.core.integrations.register({ slug: INTEG, description: "Vercel", config: {}, }), resolveValue: (name: string) => ctx.connections.resolveValue({ owner: "org", integration: INTEG, name: ConnectionName.make(name), }), }), }))(); const config = makeTestConfig({ plugins: [gatedPlugin] as const }); const executor = yield* createExecutor(config); yield* executor.gated.seed(); const createWith = (value: string) => Effect.result( executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value, }), ); const firstFiber = yield* Effect.forkChild(createWith("first-value")); yield* Deferred.await(firstWriteEntered); const second = yield* createWith("second-value"); yield* Deferred.succeed(releaseFirstWrite, undefined); const first = yield* Fiber.join(firstFiber); const attempts = [ { result: first, value: "first-value" }, { result: second, value: "second-value" }, ]; const winners = attempts.filter((attempt) => Result.isSuccess(attempt.result)); const losers = attempts.filter((attempt) => Result.isFailure(attempt.result)); expect(winners).toHaveLength(1); expect(losers).toHaveLength(1); const loser = losers[0]; if (!loser || !Result.isFailure(loser.result)) return; expect(loser.result.failure).toBeInstanceOf(ConnectionAlreadyExistsError); // Exactly one connection survived, and it resolves to the WINNER's // value — the losing create never reached the provider. const connections = yield* executor.connections.list(); expect(connections).toHaveLength(1); const value = yield* executor.gated.resolveValue("main"); expect(value).toBe(winners[0]?.value); }), ), ); // When both creates observe absence, both reach the insert and the primary // key breaks the tie — the loser must still get the typed 409, not a raw // unique-constraint storage failure. The proxy blinds every connection-table // read for the second create, so its early and transactional checks both // miss the existing row and its insert genuinely collides in the database. it.effect("maps a lost insert race to the typed 409, not a storage failure", () => Effect.gen(function* () { let blind = false; const blindfoldConnectionReads = (db: FumaDb): FumaDb => { const wrap = (inner: FumaDb): FumaDb => new Proxy(inner, { get(target, prop) { if (prop === "withContext") { return (context: unknown) => wrap((target.withContext as (c: unknown) => FumaDb)(context)); } if (prop === "transaction") { return (run: (tx: FumaDb) => Promise<unknown>) => (target.transaction as (r: (tx: FumaDb) => Promise<unknown>) => Promise<unknown>)( (tx) => run(wrap(tx)), ); } if (prop === "findFirst") { return (table: unknown, query: unknown) => blind && table === "connection" ? Promise.resolve(null) : (target.findFirst as (t: unknown, q: unknown) => Promise<unknown>)( table, query, ); } return Reflect.get(target, prop); }, }); return wrap(db); }; const config = makeTestConfig({ plugins: [demoPlugin] as const }); const executor = yield* createExecutor({ ...config, db: blindfoldConnectionReads(config.db), }); yield* executor.demo.seed(); yield* executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "first-value", }); blind = true; const result = yield* Effect.result( executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "second-value", }), ); blind = false; expect(Result.isFailure(result)).toBe(true); if (!Result.isFailure(result)) return; expect(result.failure).toBeInstanceOf(ConnectionAlreadyExistsError); // The losing insert wrote nothing: the original secret is untouched. const connections = yield* executor.connections.list(); expect(connections).toHaveLength(1); const value = yield* executor.demo.resolveValue("org", "main"); expect(value).toBe("first-value"); }), ); it.effect("allows the same name under a different owner", () => Effect.gen(function* () { const executor = yield* setup(); yield* executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "org-token", }); const personal = yield* executor.connections.create({ owner: "user", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "user-token", }); expect(String(personal.address)).toBe("tools.vercel.user.main"); expect((yield* executor.connections.list()).length).toBe(2); }), ); it.effect("external `from` references a provider item without writing it", () => Effect.gen(function* () { const executor = yield* setup(); const connection = yield* executor.connections.create({ owner: "org", name: ConnectionName.make("byo"), integration: INTEG, template: TEMPLATE, from: { provider: ProviderKey.make("memory"), id: ProviderItemId.make("ext-item"), }, }); expect(connection.provider).toBe(ProviderKey.make("memory")); // No value was stored (external reference) — resolveValue returns null. const value = yield* executor.demo.resolveValue("org", "byo"); expect(value).toBeNull(); }), ); it.effect("create on an unknown integration fails with IntegrationNotFoundError", () => Effect.gen(function* () { const executor = yield* setup(); const result = yield* Effect.result( executor.connections.create({ owner: "org", name: ConnectionName.make("x"), integration: IntegrationSlug.make("unknown"), template: TEMPLATE, value: "v", }), ); expect(Result.isFailure(result)).toBe(true); if (!Result.isFailure(result)) return; expect(Predicate.isTagged("IntegrationNotFoundError")(result.failure)).toBe(true); }), ); // A credentialed connection is "born wired": it must reference at least one // credential input. An empty binding (an empty `values`/`inputs` map) produces // a credential with no credential — it persists, produces a full tool catalog, // and then fails every invocation with `connection_value_missing`. These cases // must be rejected at create with a typed `InvalidConnectionInputError` (the // HTTP edge answers 400 with the reason, not an opaque 500). The exception is // the no-auth template ("none"), where zero inputs and an empty `item_ids` // map are the canonical shape — covered below. (An empty-STRING value is also // allowed, and an external `from` that resolves to null is a supported case — // both covered by their own tests.) it.effect("rejects an empty `values` map on a credentialed template and persists nothing", () => Effect.gen(function* () { const executor = yield* setup(); const result = yield* Effect.result( executor.connections.create({ owner: "org",Lines 1–500 of 3312. Load more
import { describe, expect, it } from "@effect/vitest"; import { Cause, Deferred, Effect, Exit, Fiber, Inspectable, Logger, Option, Predicate, Result, Schema, Tracer, } from "effect"; import { AuthTemplateSlug, ConnectionName, IntegrationSlug, ProviderItemId, ProviderKey, Subject, Tenant, ToolAddress, ToolName, } from "./ids"; import { ConnectionAlreadyExistsError } from "./errors"; import { createExecutor } from "./executor"; import { StorageError, type FumaDb } from "./fuma-runtime"; import { HealthCheckResult } from "./health-check"; import { definePlugin, type ResolveToolsResult } from "./plugin"; import type { CredentialProvider } from "./provider"; import { makeTestConfig, makeTestExecutor } from "./testing"; import { ToolResult } from "./tool-result"; // removed: v1 connection-refresh lifecycle, ConnectionProvider.refresh, // SecretProvider, accessToken token-refresh + in-flight dedup tests — the v2 // model folds secret/connection into one provider-resolved Connection, and OAuth // refresh is core's responsibility (stubbed for milestone 1). The cases below // cover the v2 connection surface: create (inline + external), list, get, // remove, refresh, and per-connection tool production. const memoryProvider = (): CredentialProvider => { const store = new Map<string, string>(); return { key: ProviderKey.make("memory"), writable: true, get: (id) => Effect.sync(() => store.get(String(id)) ?? null), set: (id, value) => Effect.sync(() => void store.set(String(id), value)), has: (id) => Effect.sync(() => store.has(String(id))), list: () => Effect.sync(() => Array.from(store.keys()).map((key) => ({ id: ProviderItemId.make(key), name: key, })), ), }; }; const INTEG = IntegrationSlug.make("vercel"); const TEMPLATE = AuthTemplateSlug.make("apiKey"); /** Wrap a test `FumaDb` so every transaction it opens is observable. The * executor re-binds its own owner context onto the handle it is given, so the * wrapper must forward `withContext` re-wrapped — otherwise the instrument is * dropped before any executor query runs. */ const instrumentTransactions = ( db: FumaDb, hooks: { readonly enter: () => void; readonly exit: () => void }, ): FumaDb => { const wrap = (inner: FumaDb): FumaDb => new Proxy(inner, { get(target, prop) { if (prop === "withContext") { return (context: unknown) => wrap((target.withContext as (c: unknown) => FumaDb)(context)); } if (prop === "transaction") { return async (run: Parameters<FumaDb["transaction"]>[0]) => { hooks.enter(); // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: test instrument must unwind on both outcomes try { return await target.transaction(run); } finally { hooks.exit(); } }; } return Reflect.get(target, prop); }, }); return wrap(db); }; const ConnectionListHealthOutput = Schema.Struct({ connections: Schema.Array(Schema.Struct({ lastHealth: Schema.NullOr(HealthCheckResult) })), }); const decodeConnectionListHealthOutput = Schema.decodeUnknownEffect(ConnectionListHealthOutput); const demoPlugin = definePlugin(() => ({ id: "demo" as const, credentialProviders: [memoryProvider()], storage: () => ({}), resolveTools: () => Effect.succeed({ tools: [ { name: ToolName.make("deploy"), description: "deploy" }, { name: ToolName.make("list"), description: "list" }, ], }), invokeTool: ({ toolRow, credential }) => Effect.succeed({ ran: toolRow.name, value: credential.value }), extension: (ctx) => ({ seed: () => ctx.core.integrations.register({ slug: INTEG, description: "Vercel", config: {}, }), resolveValue: (owner: "org" | "user", name: string) => ctx.connections.resolveValue({ owner, integration: INTEG, name: ConnectionName.make(name), }), }), }))(); const setup = () => makeTestExecutor({ plugins: [demoPlugin] as const }).pipe( Effect.tap((executor) => executor.demo.seed()), ); describe("connections.create", () => { it.effect("inline value writes to the default writable provider and produces tools", () => Effect.gen(function* () { const executor = yield* setup(); const connection = yield* executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "secret-token", }); expect(connection.provider).toBe(ProviderKey.make("memory")); expect(String(connection.address)).toBe("tools.vercel.org.main"); const tools = yield* executor.tools.list(); expect(tools.map((t) => String(t.name)).sort()).toEqual(["deploy", "list"]); // The inline value is resolvable via the connection's provider. const value = yield* executor.demo.resolveValue("org", "main"); expect(value).toBe("secret-token"); }), ); it.effect("normalizes free-form names into JS-callable connection identifiers", () => Effect.gen(function* () { const executor = yield* setup(); const connection = yield* executor.connections.create({ owner: "org", name: ConnectionName.make("my-api-key"), integration: INTEG, template: TEMPLATE, value: "secret-token", }); expect(String(connection.name)).toBe("myApiKey"); expect(String(connection.address)).toBe("tools.vercel.org.myApiKey"); const tools = yield* executor.tools.list(); expect(tools.map((t) => String(t.address)).sort()).toEqual([ "tools.vercel.org.myApiKey.deploy", "tools.vercel.org.myApiKey.list", ]); const value = yield* executor.demo.resolveValue("org", "myApiKey"); expect(value).toBe("secret-token"); }), ); // Create is never a replace: a second create with the same (owner, // integration, name) must fail with ConnectionAlreadyExistsError and leave // the first connection fully intact — including its stored secret, which a // silent upsert would overwrite (the pasted value's item id is derived from // the name, so the provider write alone clobbers it). it.effect("rejects a duplicate (owner, integration, name) and keeps the original intact", () => Effect.gen(function* () { const executor = yield* setup(); yield* executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "original-token", description: "original", }); const result = yield* Effect.result( executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "clobbered-token", description: "clobbered", }), ); expect(Result.isFailure(result)).toBe(true); if (!Result.isFailure(result)) return; expect(Predicate.isTagged("ConnectionAlreadyExistsError")(result.failure)).toBe(true); // The original row and its secret both survived. const connections = yield* executor.connections.list(); expect(connections.length).toBe(1); expect(connections[0]?.description).toBe("original"); const value = yield* executor.demo.resolveValue("org", "main"); expect(value).toBe("original-token"); }), ); // Names collide AFTER identifier normalization: "my-api-key" and "my api key" // both normalize to myApiKey, so the second must be rejected even though the // raw inputs differ. it.effect("rejects a duplicate that only collides after name normalization", () => Effect.gen(function* () { const executor = yield* setup(); yield* executor.connections.create({ owner: "org", name: ConnectionName.make("my-api-key"), integration: INTEG, template: TEMPLATE, value: "v1", }); const result = yield* Effect.result( executor.connections.create({ owner: "org", name: ConnectionName.make("my api key"), integration: INTEG, template: TEMPLATE, value: "v2", }), ); expect(Result.isFailure(result)).toBe(true); if (!Result.isFailure(result)) return; expect(Predicate.isTagged("ConnectionAlreadyExistsError")(result.failure)).toBe(true); const value = yield* executor.demo.resolveValue("org", "myApiKey"); expect(value).toBe("v1"); }), ); // The race the early duplicate check cannot answer: two creates for the same // (owner, integration, name) in flight at once. The row insert picks the // winner and the loser gets the typed 409 — and, the load-bearing part, the // provider write is winner-only. A pasted value's item id is deterministic, // so a pre-insert write from the LOSING create would silently replace the // winner's stored secret while the winner's row keeps resolving through it. // The gate parks the first create inside its provider write, so the second // create runs its full duplicate handling while the first is mid-flight. it.effect("concurrent creates: one winner, a typed 409, and the winner's secret intact", () => Effect.scoped( Effect.gen(function* () { const firstWriteEntered = yield* Deferred.make<void>(); const releaseFirstWrite = yield* Deferred.make<void>(); const store = new Map<string, string>(); let writes = 0; const gatedProvider: CredentialProvider = { key: ProviderKey.make("memory"), writable: true, get: (id) => Effect.sync(() => store.get(String(id)) ?? null), set: (id, value) => Effect.gen(function* () { writes += 1; if (writes === 1) { yield* Deferred.succeed(firstWriteEntered, undefined); yield* Deferred.await(releaseFirstWrite); } store.set(String(id), value); }), }; const gatedPlugin = definePlugin(() => ({ id: "gated" as const, credentialProviders: [gatedProvider], storage: () => ({}), resolveTools: () => Effect.succeed({ tools: [{ name: ToolName.make("deploy"), description: "deploy" }], }), invokeTool: ({ toolRow }) => Effect.succeed({ ran: toolRow.name }), extension: (ctx) => ({ seed: () => ctx.core.integrations.register({ slug: INTEG, description: "Vercel", config: {}, }), resolveValue: (name: string) => ctx.connections.resolveValue({ owner: "org", integration: INTEG, name: ConnectionName.make(name), }), }), }))(); const config = makeTestConfig({ plugins: [gatedPlugin] as const }); const executor = yield* createExecutor(config); yield* executor.gated.seed(); const createWith = (value: string) => Effect.result( executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value, }), ); const firstFiber = yield* Effect.forkChild(createWith("first-value")); yield* Deferred.await(firstWriteEntered); const second = yield* createWith("second-value"); yield* Deferred.succeed(releaseFirstWrite, undefined); const first = yield* Fiber.join(firstFiber); const attempts = [ { result: first, value: "first-value" }, { result: second, value: "second-value" }, ]; const winners = attempts.filter((attempt) => Result.isSuccess(attempt.result)); const losers = attempts.filter((attempt) => Result.isFailure(attempt.result)); expect(winners).toHaveLength(1); expect(losers).toHaveLength(1); const loser = losers[0]; if (!loser || !Result.isFailure(loser.result)) return; expect(loser.result.failure).toBeInstanceOf(ConnectionAlreadyExistsError); // Exactly one connection survived, and it resolves to the WINNER's // value — the losing create never reached the provider. const connections = yield* executor.connections.list(); expect(connections).toHaveLength(1); const value = yield* executor.gated.resolveValue("main"); expect(value).toBe(winners[0]?.value); }), ), ); // When both creates observe absence, both reach the insert and the primary // key breaks the tie — the loser must still get the typed 409, not a raw // unique-constraint storage failure. The proxy blinds every connection-table // read for the second create, so its early and transactional checks both // miss the existing row and its insert genuinely collides in the database. it.effect("maps a lost insert race to the typed 409, not a storage failure", () => Effect.gen(function* () { let blind = false; const blindfoldConnectionReads = (db: FumaDb): FumaDb => { const wrap = (inner: FumaDb): FumaDb => new Proxy(inner, { get(target, prop) { if (prop === "withContext") { return (context: unknown) => wrap((target.withContext as (c: unknown) => FumaDb)(context)); } if (prop === "transaction") { return (run: (tx: FumaDb) => Promise<unknown>) => (target.transaction as (r: (tx: FumaDb) => Promise<unknown>) => Promise<unknown>)( (tx) => run(wrap(tx)), ); } if (prop === "findFirst") { return (table: unknown, query: unknown) => blind && table === "connection" ? Promise.resolve(null) : (target.findFirst as (t: unknown, q: unknown) => Promise<unknown>)( table, query, ); } return Reflect.get(target, prop); }, }); return wrap(db); }; const config = makeTestConfig({ plugins: [demoPlugin] as const }); const executor = yield* createExecutor({ ...config, db: blindfoldConnectionReads(config.db), }); yield* executor.demo.seed(); yield* executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "first-value", }); blind = true; const result = yield* Effect.result( executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "second-value", }), ); blind = false; expect(Result.isFailure(result)).toBe(true); if (!Result.isFailure(result)) return; expect(result.failure).toBeInstanceOf(ConnectionAlreadyExistsError); // The losing insert wrote nothing: the original secret is untouched. const connections = yield* executor.connections.list(); expect(connections).toHaveLength(1); const value = yield* executor.demo.resolveValue("org", "main"); expect(value).toBe("first-value"); }), ); it.effect("allows the same name under a different owner", () => Effect.gen(function* () { const executor = yield* setup(); yield* executor.connections.create({ owner: "org", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "org-token", }); const personal = yield* executor.connections.create({ owner: "user", name: ConnectionName.make("main"), integration: INTEG, template: TEMPLATE, value: "user-token", }); expect(String(personal.address)).toBe("tools.vercel.user.main"); expect((yield* executor.connections.list()).length).toBe(2); }), ); it.effect("external `from` references a provider item without writing it", () => Effect.gen(function* () { const executor = yield* setup(); const connection = yield* executor.connections.create({ owner: "org", name: ConnectionName.make("byo"), integration: INTEG, template: TEMPLATE, from: { provider: ProviderKey.make("memory"), id: ProviderItemId.make("ext-item"), }, }); expect(connection.provider).toBe(ProviderKey.make("memory")); // No value was stored (external reference) — resolveValue returns null. const value = yield* executor.demo.resolveValue("org", "byo"); expect(value).toBeNull(); }), ); it.effect("create on an unknown integration fails with IntegrationNotFoundError", () => Effect.gen(function* () { const executor = yield* setup(); const result = yield* Effect.result( executor.connections.create({ owner: "org", name: ConnectionName.make("x"), integration: IntegrationSlug.make("unknown"), template: TEMPLATE, value: "v", }), ); expect(Result.isFailure(result)).toBe(true); if (!Result.isFailure(result)) return; expect(Predicate.isTagged("IntegrationNotFoundError")(result.failure)).toBe(true); }), ); // A credentialed connection is "born wired": it must reference at least one // credential input. An empty binding (an empty `values`/`inputs` map) produces // a credential with no credential — it persists, produces a full tool catalog, // and then fails every invocation with `connection_value_missing`. These cases // must be rejected at create with a typed `InvalidConnectionInputError` (the // HTTP edge answers 400 with the reason, not an opaque 500). The exception is // the no-auth template ("none"), where zero inputs and an empty `item_ids` // map are the canonical shape — covered below. (An empty-STRING value is also // allowed, and an external `from` that resolves to null is a supported case — // both covered by their own tests.) it.effect("rejects an empty `values` map on a credentialed template and persists nothing", () => Effect.gen(function* () { const executor = yield* setup(); const result = yield* Effect.result( executor.connections.create({ owner: "org",