198 lines · 6.3 KB · TypeScript
RawDownload
import { expect, layer } from "@effect/vitest";import { Effect } from "effect";import { HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi"; import {  ConnectionId,  CreateConnectionInput,  TokenMaterial,  createExecutor,  Scope,  ScopeId,  SecretId,  type ConnectionProvider,  type SecretProvider,  SetSecretInput,  SetSourceCredentialBindingInput,  definePlugin,} from "@executor-js/sdk";import { makeTestWorkspaceLayer, TestWorkspace } from "@executor-js/sdk/testing";import {  addOpenApiTestSource,  serveOpenApiHttpApiTestServer,} from "@executor-js/plugin-openapi/testing"; import { openApiPlugin } from "./plugin"; const PingGroup = HttpApiGroup.make("default", { topLevel: true }).add(  HttpApiEndpoint.get("ping", "/ping"),);const UsageApi = HttpApi.make("usageScopeIsolation").add(PingGroup);const UsageGroupLive = HttpApiBuilder.group(UsageApi, "default", (handlers) =>  handlers.handle("ping", () => Effect.void),); const memorySecretsPlugin = definePlugin(() => {  const store = new Map<string, string>();   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],  };}); 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; layer(makeTestWorkspaceLayer({ scopes: [orgA], plugins }), { timeout: "15 seconds" })(  "OpenAPI usage scope isolation",  (it) => {    it.effect("secrets.usages does not expose binding rows outside the scope stack", () =>      Effect.scoped(        Effect.gen(function* () {          const server = yield* serveOpenApiHttpApiTestServer({            api: UsageApi,            handlersLayer: UsageGroupLive,          });          const { config } = yield* TestWorkspace;          const orgAExec = yield* createExecutor({ ...config, scopes: [orgA], plugins });          const orgBExec = yield* createExecutor({ ...config, scopes: [orgB], plugins });          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* addOpenApiTestSource(orgAExec, server, {            scope: String(orgA.id),            namespace: "secret_private_source",          });          yield* orgAExec.sources.setBinding(            SetSourceCredentialBindingInput.make({              source: { id: "secret_private_source", scope: orgA.id },              scope: orgA.id,              slotKey: "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.scoped(        Effect.gen(function* () {          const server = yield* serveOpenApiHttpApiTestServer({            api: UsageApi,            handlersLayer: UsageGroupLive,          });          const { config } = yield* TestWorkspace;          const orgAExec = yield* createExecutor({ ...config, scopes: [orgA], plugins });          const orgBExec = yield* createExecutor({ ...config, scopes: [orgB], plugins });          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* addOpenApiTestSource(orgAExec, server, {            scope: String(orgA.id),            namespace: "connection_private_source",          });          yield* orgAExec.sources.setBinding(            SetSourceCredentialBindingInput.make({              source: { id: "connection_private_source", scope: orgA.id },              scope: orgA.id,              slotKey: "oauth:connection",              value: { kind: "connection", connectionId },            }),          );           const usages = yield* orgBExec.connections.usages(connectionId);          expect(usages).toEqual([]);        }),      ),    );  },);