183 lines · 6.1 KB · TypeScript
RawDownload
import { describe, expect, it } from "@effect/vitest";import { Effect, Layer } from "effect"; import { MemberDirectory } from "@executor-js/api/server"; import { ApiKeyService } from "../auth/api-keys";import { UserStoreService } from "../auth/context";import { WorkOSClient, type WorkOSClientService } from "../auth/workos";import { WorkOsMirror, type WorkOsMirrorShape } from "../auth/workos-mirror";import { resolveProtectedPrincipal } from "./protected"; const createdAt = new Date("2026-01-01T00:00:00.000Z"); // The mirror's account row as `ensureAccount` mints it: id only, profile// columns unfilled until a WorkOS user payload arrives.const bareAccount = (id: string) => ({  id,  email: null,  firstName: null,  lastName: null,  avatarUrl: null,  workosUpdatedAt: null,  lastSignInAt: null,  createdAt,}); const stubApiKeys = Layer.succeed(ApiKeyService)({  validate: (value: string) =>    Effect.succeed(      value === "valid_user_key"        ? {            scope: "user" as const,            accountId: "user_123",            organizationId: "org_123",            keyId: "api_key_123",          }        : null,    ),  listUserKeys: () => Effect.succeed([]),  createUserKey: () => Effect.die("protected API auth test does not create API keys"),  revokeUserKey: () => Effect.void,  listOrgKeys: () => Effect.die("auth resolution test does not list org API keys"),  createOrgKey: () => Effect.die("auth resolution test does not create org API keys"),  revokeOrgKey: () => Effect.die("auth resolution test does not revoke org API keys"),}); const stubWorkOS = Layer.succeed(  WorkOSClient,  new Proxy({} as WorkOSClientService, {    get: (_target, prop) => {      return () => Effect.die(`unexpected WorkOSClient.${String(prop)} call`);    },  }),); // The mirror as the directory reads it: user_123 holds an active membership in// org_123 and nothing else. Membership is always read from the mirror, never// from WorkOS.const stubDirectory = Layer.succeed(MemberDirectory)({  membership: (accountId, organizationId) =>    Effect.succeed(      accountId === "user_123" && organizationId === "org_123"        ? {            accountId,            membershipId: `om_${accountId}_${organizationId}`,            organizationId,            email: null,            name: null,            avatarUrl: null,            role: "member",            status: "active" as const,            lastActiveAt: null,          }        : null,    ),  membershipById: () => Effect.die("bearer resolution does not look up by membership id"),  membershipsOf: () => Effect.die("bearer resolution reads one membership, not the list"),  members: () => Effect.die("bearer resolution does not list members"),  membersById: () => Effect.die("bearer resolution does not batch members"),  findByEmail: () => Effect.die("bearer resolution does not resolve emails"),}); const stubUsers = Layer.succeed(UserStoreService)({  use: (_op, fn) =>    Effect.promise(() =>      fn({        ensureAccount: async (id: string) => bareAccount(id),        getAccount: async (id: string) => bareAccount(id),        upsertOrganization: async (org: { id: string; name: string }) => ({          ...org,          slug: `org-slug-${org.id}`,          backfilledAt: createdAt,          deletedAt: null,          workosUpdatedAt: null,          createdAt,        }),        getOrganization: async (id: string) => ({          id,          name: `Org ${id}`,          slug: `org-slug-${id}`,          backfilledAt: createdAt,          deletedAt: null,          workosUpdatedAt: null,          createdAt,        }),        getOrganizationBySlug: async (slug: string) => ({          id: "org_by_slug",          name: `Org ${slug}`,          slug,          backfilledAt: createdAt,          deletedAt: null,          workosUpdatedAt: null,          createdAt,        }),        markOrganizationDeleted: async () => null,        deleteOrganizationCascade: async () => {},      }),    ),}); // Authorization scans an organization the backfill never covered before it// reads the mirror (`auth/organization.ts`); every org row above is marked// backfilled, so the scan is never reached and the mirror is never written.const stubMirror = Layer.succeed(  WorkOsMirror,  new Proxy({} as WorkOsMirrorShape, {    get: (_target, prop) => () => Effect.die(`unexpected WorkOsMirror.${String(prop)} call`),  }),); const run = (request: Request) =>  resolveProtectedPrincipal(request).pipe(    Effect.provide(Layer.mergeAll(stubApiKeys, stubWorkOS, stubUsers, stubDirectory, stubMirror)),  ); describe("protected API key auth", () => {  it.effect("resolves a valid bearer API key into protected identity", () =>    Effect.gen(function* () {      const identity = yield* run(        new Request("https://executor.test/api/tools", {          headers: { authorization: "Bearer valid_user_key" },        }),      );       expect(identity).toEqual({        kind: "member",        accountId: "user_123",        organizationId: "org_123",        organizationName: "Org org_123",        organizationSlug: "org-slug-org_123",        email: "",        name: null,        avatarUrl: null,        roles: [],        // The stub membership carries no role slug — normalization FAILS        // CLOSED to plain member, so the executor binds workspace writes off.        orgRoleModel: "organization",        orgRole: "member",      });    }),  );   it.effect("rejects invalid bearer API keys", () =>    Effect.gen(function* () {      const error = yield* Effect.flip(        run(          new Request("https://executor.test/api/tools", {            headers: { authorization: "Bearer invalid_user_key" },          }),        ),      );       // The resolver now raises the SHARED `Unauthorized` carrying the same      // machine code; cloud's failure strategy renders it as the byte-identical      // 401 `{ error: "Invalid API key", code: "invalid_api_key" }`.      expect(error).toMatchObject({        _tag: "Unauthorized",        code: "invalid_api_key",        message: "Invalid API key",      });    }),  );});