import { describe, expect, it } from "@effect/vitest"; import { Effect } from "effect"; import { ConnectionId, CreateConnectionInput, TokenMaterial, createExecutor, makeTestConfig, Scope, ScopeId, SecretId, type ConnectionProvider, type SecretProvider, SetSecretInput, definePlugin, } from "@executor-js/sdk"; import { openApiPlugin } from "./plugin"; import { OpenApiSourceBindingInput } from "./types"; const specJson = JSON.stringify({ openapi: "3.0.0", info: { title: "Scoped Usage", version: "1.0.0" }, paths: { "/ping": { get: { operationId: "ping", responses: { "200": { description: "ok" } } }, }, }, }); const memorySecretsPlugin = definePlugin(() => { const store = new Map(); const provider: SecretProvider = { key: "memory", writable: true, get: (id, scope) => Effect.sync(() => store.get(`${scope}\u0000${id}`) ?? null), set: (id, value, scope) => Effect.sync(() => { store.set(`${scope}\u0000${id}`, value); }), delete: (id, scope) => Effect.sync(() => store.delete(`${scope}\u0000${id}`)), }; return { id: "test-memory-secrets" as const, storage: () => ({}), secretProviders: [provider], }; }); const connectionProviderPlugin = definePlugin(() => { const provider: ConnectionProvider = { key: "test-oauth", }; return { id: "test-connection-provider" as const, storage: () => ({}), connectionProviders: [provider], }; }); describe("OpenAPI usage scope isolation", () => { it.effect("secrets.usages does not expose binding rows outside the scope stack", () => Effect.gen(function* () { const orgA = Scope.make({ id: ScopeId.make("org-a"), name: "Org A", createdAt: new Date(), }); const orgB = Scope.make({ id: ScopeId.make("org-b"), name: "Org B", createdAt: new Date(), }); const plugins = [memorySecretsPlugin(), openApiPlugin()] as const; const config = makeTestConfig({ scopes: [orgA], plugins }); const orgAExec = yield* createExecutor({ ...config, scopes: [orgA] }); const orgBExec = yield* createExecutor({ ...config, scopes: [orgB] }); const secretId = SecretId.make("org-a-api-key"); yield* orgAExec.secrets.set( SetSecretInput.make({ id: secretId, scope: orgA.id, name: "Org A API Key", value: "secret", provider: "memory", }), ); yield* orgBExec.secrets.set( SetSecretInput.make({ id: secretId, scope: orgB.id, name: "Org B API Key", value: "different-secret", provider: "memory", }), ); yield* orgAExec.openapi.addSpec({ spec: specJson, scope: String(orgA.id), namespace: "private_source", baseUrl: "http://example.com", }); yield* orgAExec.openapi.setSourceBinding( OpenApiSourceBindingInput.make({ sourceId: "private_source", sourceScope: orgA.id, scope: orgA.id, slot: "header:authorization", value: { kind: "secret", secretId }, }), ); const usages = yield* orgBExec.secrets.usages(secretId); expect(usages).toEqual([]); }), ); it.effect("connections.usages does not expose binding rows outside the scope stack", () => Effect.gen(function* () { const orgA = Scope.make({ id: ScopeId.make("org-a"), name: "Org A", createdAt: new Date(), }); const orgB = Scope.make({ id: ScopeId.make("org-b"), name: "Org B", createdAt: new Date(), }); const plugins = [memorySecretsPlugin(), connectionProviderPlugin(), openApiPlugin()] as const; const config = makeTestConfig({ scopes: [orgA], plugins }); const orgAExec = yield* createExecutor({ ...config, scopes: [orgA] }); const orgBExec = yield* createExecutor({ ...config, scopes: [orgB] }); const connectionId = ConnectionId.make("org-a-connection"); yield* orgAExec.connections.create( CreateConnectionInput.make({ id: connectionId, scope: orgA.id, provider: "test-oauth", identityLabel: "Org A connection", accessToken: TokenMaterial.make({ secretId: SecretId.make("org-a-connection-access"), name: "Org A access", value: "access", }), refreshToken: null, expiresAt: null, oauthScope: null, providerState: null, }), ); yield* orgBExec.connections.create( CreateConnectionInput.make({ id: connectionId, scope: orgB.id, provider: "test-oauth", identityLabel: "Org B connection", accessToken: TokenMaterial.make({ secretId: SecretId.make("org-b-connection-access"), name: "Org B access", value: "access", }), refreshToken: null, expiresAt: null, oauthScope: null, providerState: null, }), ); yield* orgAExec.openapi.addSpec({ spec: specJson, scope: String(orgA.id), namespace: "private_source", baseUrl: "http://example.com", }); yield* orgAExec.openapi.setSourceBinding( OpenApiSourceBindingInput.make({ sourceId: "private_source", sourceScope: orgA.id, scope: orgA.id, slot: "oauth:connection", value: { kind: "connection", connectionId }, }), ); const usages = yield* orgBExec.connections.usages(connectionId); expect(usages).toEqual([]); }), ); });