154 lines · 4.6 KB · TypeScript
RawDownload
import type {  AccountId,  CredentialSlot,  Source,  SourceAuth,} from "#schema";import * as Context from "effect/Context";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Option from "effect/Option"; import { ControlPlaneStore, type ControlPlaneStoreShape } from "./store";import {  authArtifactFromSourceAuth,  resolveAuthArtifactMaterial,  type ResolvedSourceAuthMaterial,} from "./auth-artifacts";import { resolveAuthArtifactMaterialWithLeases } from "./auth-leases";import type {  ResolveSecretMaterial,  SecretMaterialResolveContext,} from "./secret-material-providers";import { SecretMaterialResolverService } from "./secret-material-providers"; const authForSlot = (input: {  source: Source;  slot: CredentialSlot;}): SourceAuth => {  if (input.slot === "runtime") {    return input.source.auth;  }   if (input.source.importAuthPolicy === "reuse_runtime") {    return input.source.auth;  }   if (input.source.importAuthPolicy === "none") {    return { kind: "none" };  }   return input.source.importAuth;}; export type RuntimeSourceAuthMaterialShape = {  resolve: (input: {    source: Source;    slot?: CredentialSlot;    actorAccountId?: AccountId | null;    context?: SecretMaterialResolveContext;  }) => Effect.Effect<ResolvedSourceAuthMaterial, Error, never>;}; export class RuntimeSourceAuthMaterialService extends Context.Tag(  "#runtime/RuntimeSourceAuthMaterialService",)<RuntimeSourceAuthMaterialService, RuntimeSourceAuthMaterialShape>() {} export const resolveSourceAuthMaterialWithDeps = (input: {  source: Source;  slot?: CredentialSlot;  actorAccountId?: AccountId | null;  rows?: ControlPlaneStoreShape;  resolveSecretMaterial: ResolveSecretMaterial;  context?: SecretMaterialResolveContext;}): Effect.Effect<ResolvedSourceAuthMaterial, Error, never> =>  Effect.gen(function* () {    const slot = input.slot ?? "runtime";     if (input.rows !== undefined) {      const candidateSlots =        slot === "import" && input.source.importAuthPolicy === "reuse_runtime"          ? ["import", "runtime"] satisfies ReadonlyArray<CredentialSlot>          : [slot] satisfies ReadonlyArray<CredentialSlot>;       for (const candidateSlot of candidateSlots) {        const artifactOption = yield* input.rows.authArtifacts.getByWorkspaceSourceAndActor({          workspaceId: input.source.workspaceId,          sourceId: input.source.id,          actorAccountId: input.actorAccountId ?? null,          slot: candidateSlot,        });         if (Option.isSome(artifactOption)) {          return yield* resolveAuthArtifactMaterialWithLeases({            rows: input.rows,            artifact: artifactOption.value,            resolveSecretMaterial: input.resolveSecretMaterial,            context: input.context,          });        }      }    }     const artifact = authArtifactFromSourceAuth({      source: input.source,      auth: authForSlot({        source: input.source,        slot,      }),      slot,      actorAccountId: input.actorAccountId ?? null,    });     if (input.rows !== undefined) {      return yield* resolveAuthArtifactMaterialWithLeases({        rows: input.rows,        artifact,        resolveSecretMaterial: input.resolveSecretMaterial,        context: input.context,      });    }     if (      artifact?.artifactKind === "oauth2_authorized_user"      || artifact?.artifactKind === "provider_grant_ref"      || artifact?.artifactKind === "mcp_oauth"    ) {      return yield* Effect.fail(        new Error("Dynamic auth artifacts require persistence-backed lease resolution"),      );    }     return yield* resolveAuthArtifactMaterial({      artifact,      resolveSecretMaterial: input.resolveSecretMaterial,      context: input.context,    });  }); export const resolveSourceAuthMaterial = (input: {  source: Source;  slot?: CredentialSlot;  actorAccountId?: AccountId | null;  context?: SecretMaterialResolveContext;}): Effect.Effect<ResolvedSourceAuthMaterial, Error, RuntimeSourceAuthMaterialService> =>  Effect.flatMap(RuntimeSourceAuthMaterialService, (service) => service.resolve(input)); export const RuntimeSourceAuthMaterialLive = Layer.effect(  RuntimeSourceAuthMaterialService,  Effect.gen(function* () {    const rows = yield* ControlPlaneStore;    const resolveSecretMaterial = yield* SecretMaterialResolverService;     return RuntimeSourceAuthMaterialService.of({      resolve: (input) =>        resolveSourceAuthMaterialWithDeps({          ...input,          rows,          resolveSecretMaterial,        }),    });  }),); export type { ResolvedSourceAuthMaterial } from "./auth-artifacts";