1118 lines · 42.1 KB · TypeScript
RawDownload
import { createClerkClient, verifyToken } from "@clerk/backend";import { sql as drizzleSql } from "drizzle-orm";import * as Crypto from "effect/Crypto";import * as Context from "effect/Context";import * as DateTime from "effect/DateTime";import * as Duration from "effect/Duration";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Record from "effect/Record";import * as Redacted from "effect/Redacted";import * as Schema from "effect/Schema";import * as Tracer from "effect/Tracer";import * as HttpEffect from "effect/unstable/http/HttpEffect";import * as HttpMiddleware from "effect/unstable/http/HttpMiddleware";import * as HttpRouter from "effect/unstable/http/HttpRouter";import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";import * as HttpTraceContext from "effect/unstable/http/HttpTraceContext";import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder";import * as HttpApiError from "effect/unstable/httpapi/HttpApiError";import { encodeOAuthScope } from "@t3tools/shared/oauthScope";import { httpHeaderRedactionLayer } from "@t3tools/shared/httpObservability"; import {  RelayApi,  RelayAgentActivityPublishProofExpiredError,  RelayAgentActivityPublishProofInvalidError,  RelayClientAuth,  RelayClientPrincipal,  RelayAccessTokenType,  RelayDpopClientAuth,  RelayEnvironmentConnectScope,  RelayEnvironmentStatusScope,  RelayMobileRegistrationScope,  RelayAuthInvalidError,  type RelayAuthInvalidReason,  RelayEnvironmentAuth,  RelayEnvironmentConnectNotAuthorizedError,  RelayEnvironmentEndpointTimedOutError,  RelayEnvironmentEndpointUnavailableError,  RelayEnvironmentLinkFailedError,  RelayEnvironmentLinkProofExpiredError,  RelayEnvironmentLinkProofInvalidError,  RelayEnvironmentLinkUnavailableError,  RelayEnvironmentPrincipal,  type RelayEnvironmentConnectRequest,  type RelayDpopAccessTokenScope,  RelayInternalError,} from "@t3tools/contracts/relay";import { normalizeRelayIssuer } from "@t3tools/shared/relayJwt"; import * as DeliveryAttempts from "../agentActivity/DeliveryAttempts.ts";import * as AgentActivityRows from "../agentActivity/AgentActivityRows.ts";import * as Devices from "../agentActivity/Devices.ts";import * as DpopProofs from "../auth/DpopProofs.ts";import * as RelayTokens from "../auth/RelayTokens.ts";import * as EnvironmentCredentials from "../environments/EnvironmentCredentials.ts";import * as EnvironmentLinks from "../environments/EnvironmentLinks.ts";import * as LiveActivities from "../agentActivity/LiveActivities.ts";import * as RelayConfiguration from "../Config.ts";import * as AgentActivityPublisher from "../agentActivity/AgentActivityPublisher.ts";import * as EnvironmentConnector from "../environments/EnvironmentConnector.ts";import * as EnvironmentLinker from "../environments/EnvironmentLinker.ts";import * as ManagedEndpointProvider from "../environments/ManagedEndpointProvider.ts";import * as ManagedEndpointAllocations from "../environments/ManagedEndpointAllocations.ts";import * as EnvironmentPublishSignatures from "../environments/EnvironmentPublishSignatures.ts";import * as MobileRegistrations from "../agentActivity/MobileRegistrations.ts";import { withSpanAttributes } from "../observability.ts";import * as RelayDb from "../db.ts"; const relayCorsAllowedMethods = ["GET", "POST", "DELETE", "OPTIONS"] as const;const relayCorsAllowedHeaders = [  "authorization",  "b3",  "traceparent",  "content-type",  "dpop",] as const;const relayCorsExposedHeaders = ["traceparent", "www-authenticate"] as const; const relayCorsHeaders = {  "access-control-allow-origin": "*",  "access-control-expose-headers": relayCorsExposedHeaders.join(","),} as const; const relayCorsPreflightHeaders = {  ...relayCorsHeaders,  "access-control-allow-methods": relayCorsAllowedMethods.join(","),  "access-control-allow-headers": relayCorsAllowedHeaders.join(","),  "access-control-max-age": "86400",} as const; const appendRelayCredentialResponseHeaders = HttpEffect.appendPreResponseHandler(  (_request, response) =>    Effect.succeed(      HttpServerResponse.setHeaders(response, {        "cache-control": "no-store",        pragma: "no-cache",      }),    ),); const appendRelayDpopChallengeHeader = HttpEffect.appendPreResponseHandler((_request, response) =>  Effect.succeed(    response.status === 401      ? HttpServerResponse.setHeader(response, "www-authenticate", "DPoP")      : response,  ),); const appendRelayTraceContextResponseHeader = Effect.gen(function* () {  const span = yield* Effect.currentParentSpan;  if (span._tag !== "Span") {    return;  }  const traceparent = HttpTraceContext.toHeaders(span).traceparent;  if (traceparent === undefined) {    return;  }  yield* HttpEffect.appendPreResponseHandler((_request, response) =>    Effect.succeed(HttpServerResponse.setHeader(response, "traceparent", traceparent)),  );}).pipe(Effect.ignore); export const relayCors = HttpRouter.middleware(  Effect.fnUntraced(function* <E, R>(    httpEffect: Effect.Effect<      HttpServerResponse.HttpServerResponse,      E,      HttpServerRequest.HttpServerRequest | R    >,  ) {    const request = yield* HttpServerRequest.HttpServerRequest;    if (request.method === "OPTIONS") {      return HttpServerResponse.empty({        status: 204,        headers: relayCorsPreflightHeaders,      });    }    const response = yield* httpEffect;    return HttpServerResponse.setHeaders(response, relayCorsHeaders);  }),  { global: true },); export const relayNotFoundRoute = HttpRouter.add(  "*",  "/*",  HttpServerResponse.empty({ status: 404 }),); export const relayDocsRedirectRoute = HttpRouter.add(  "GET",  "/",  HttpServerResponse.redirect("/docs"),); export const traceRelayHttpRequest = <E, R>(  httpEffect: Effect.Effect<    HttpServerResponse.HttpServerResponse,    E,    HttpServerRequest.HttpServerRequest | R  >,) =>  // HttpMiddleware finalizes its span on the dispatcher; do not close a request-scoped exporter first.  HttpMiddleware.tracer(    appendRelayTraceContextResponseHeader.pipe(Effect.andThen(httpEffect)),  ).pipe(Effect.ensuring(Effect.yieldNow)); export const traceRelayHttpRequestWith = <E, R, LayerError, LayerRequirements>(  httpEffect: Effect.Effect<    HttpServerResponse.HttpServerResponse,    E,    HttpServerRequest.HttpServerRequest | R  >,  tracerLayer: Layer.Layer<never, LayerError, LayerRequirements>,) =>  traceRelayHttpRequest(httpEffect).pipe(    Effect.provide(Layer.merge(tracerLayer, httpHeaderRedactionLayer)),  ); export const withoutCapturedParentSpan = <A, E, R>(  effect: Effect.Effect<A, E, R>,): Effect.Effect<A, E, R> =>  Effect.withFiber((fiber) => {    const context = fiber.context;    // HttpApiBuilder captures its build context for route handlers; an event parent would outlive export.    fiber.setContext(Context.omit(Tracer.ParentSpan)(context));    return effect.pipe(Effect.ensuring(Effect.sync(() => fiber.setContext(context))));  }); export const relayClientAuthLayer = Layer.effect(  RelayClientAuth,  Effect.gen(function* () {    const config = yield* RelayConfiguration.RelayConfiguration;    return {      clientBearer: Effect.fn("relay.auth.client.bearer")(function* (httpEffect, { credential }) {        const token = readHttpAuthorizationCredential(credential);        const verified = yield* verifyRelayClientBearerToken(config, token).pipe(          Effect.tapError((error) =>            Effect.annotateCurrentSpan(              "relay.auth.clerk_verification_failure",              clerkVerificationFailureReason(error.cause),            ),          ),          Effect.catch(() => relayAuthInvalidError("invalid_bearer")),        );        if (!verified.sub) {          yield* Effect.annotateCurrentSpan({            "relay.auth.clerk_verification_failure": "missing_subject",          });          return yield* relayAuthInvalidError("invalid_bearer");        }        yield* Effect.annotateCurrentSpan({          "relay.auth.mode": verified.mode,          "relay.auth.subject": verified.sub,        });         return yield* httpEffect.pipe(          withSpanAttributes({ "user.id": verified.sub }),          Effect.provideService(RelayClientPrincipal, {            userId: verified.sub,            token,          }),        );      }),    };  }),); export const relayEnvironmentAuthLayer = Layer.effect(  RelayEnvironmentAuth,  Effect.gen(function* () {    const credentials = yield* EnvironmentCredentials.EnvironmentCredentials;    return {      environmentBearer: Effect.fn("relay.auth.environment.bearer")(function* (        httpEffect,        { credential },      ) {        const token = readHttpAuthorizationCredential(credential);        const principal = yield* credentials          .authenticate(token)          .pipe(            Effect.catchTag("EnvironmentCredentialAuthenticatePersistenceError", () =>              relayInternalErrorResponse("persistence_failed"),            ),          );        if (principal._tag === "None") {          return yield* relayAuthInvalidError("not_authorized");        }        yield* Effect.annotateCurrentSpan({          "relay.auth.mode": "environment_credential",        });        return yield* httpEffect.pipe(          withSpanAttributes({            "relay.environment_id": principal.value.environmentId,          }),          Effect.provideService(RelayEnvironmentPrincipal, principal.value),        );      }),    };  }),); export const relayDpopClientAuthLayer = Layer.effect(  RelayDpopClientAuth,  Effect.gen(function* () {    const relayTokens = yield* RelayTokens.RelayTokens;    return {      relayDpop: Effect.fn("relay.auth.dpop_client")(function* (httpEffect, { credential }) {        yield* appendRelayDpopChallengeHeader;        const request = yield* HttpServerRequest.HttpServerRequest;        if (!isDpopAuthorizationHeader(request.headers.authorization)) {          return yield* relayAuthInvalidError("invalid_bearer");        }        const token = readHttpAuthorizationCredential(credential);        const now = yield* DateTime.now;        const verified = yield* relayTokens.verifyDpopAccessToken({          token,          nowEpochSeconds: Math.floor(now.epochMilliseconds / 1_000),        });        if (!verified) {          return yield* relayAuthInvalidError("invalid_bearer");        }        yield* Effect.annotateCurrentSpan({          "relay.auth.mode": "dpop",          "relay.auth.subject": verified.sub,        });        return yield* httpEffect.pipe(          withSpanAttributes({ "user.id": verified.sub }),          Effect.provideService(RelayClientPrincipal, {            userId: verified.sub,            token,            proofKeyThumbprint: verified.cnf.jkt,            dpopScopes: verified.scope,          }),        );      }),    };  }),); function isDpopAuthorizationHeader(value: string | undefined): boolean {  return /^DPoP +/iu.test(value ?? "");} function readHttpAuthorizationCredential(credential: Redacted.Redacted<string>): string {  // Effect beta.73 leaves the scheme separator in decoded HTTP credentials.  return Redacted.value(credential).trimStart();} export const metadataApi = HttpApiBuilder.group(  RelayApi,  "metadata",  Effect.fnUntraced(function* (handlers) {    const settings = yield* RelayConfiguration.RelayConfiguration;    const issuer = normalizeRelayIssuer(settings.relayIssuer);    const scopes = [      RelayEnvironmentConnectScope,      RelayEnvironmentStatusScope,      RelayMobileRegistrationScope,    ] as const;    return handlers      .handle("authorizationServer", () =>        Effect.succeed({          issuer,          token_endpoint: `${issuer}/v1/client/dpop-token`,          grant_types_supported: ["urn:ietf:params:oauth:grant-type:token-exchange"],          token_endpoint_auth_methods_supported: ["none"],          dpop_signing_alg_values_supported: ["ES256"],          scopes_supported: scopes,        }),      )      .handle("protectedResource", () =>        Effect.succeed({          resource: issuer,          authorization_servers: [issuer],          scopes_supported: scopes,          dpop_bound_access_tokens_required: true,          dpop_signing_alg_values_supported: ["ES256"],        }),      );  }),); export const healthApi = HttpApiBuilder.group(  RelayApi,  "health",  Effect.fnUntraced(function* (handlers) {    const db = yield* RelayDb.RelayDb;    return handlers.handle(      "health",      Effect.fn("relay.api.health")(        function* () {          yield* db.execute(drizzleSql`SELECT 1`);          return { ok: true, service: "relay" as const };        },        Effect.catch(() => relayInternalErrorResponse("database_unavailable")),      ),    );  }),); export const mobileApi = HttpApiBuilder.group(  RelayApi,  "mobile",  Effect.fnUntraced(function* (handlers) {    const registrations = yield* MobileRegistrations.MobileRegistrations;    const dpopProofs = yield* DpopProofs.DpopProofReplay;    return handlers      .handle(        "registerDevice",        Effect.fn("relay.api.mobile.registerDevice")(function* (args) {          const { payload } = args;          const { userId, token } = yield* RelayClientPrincipal;          const proofKeyThumbprint = yield* requireDpopPrincipalScope("mobile:registration");          yield* requireDpopThumbprint(proofKeyThumbprint, {            expectedAccessToken: token,          }).pipe(Effect.provideService(DpopProofs.DpopProofReplay, dpopProofs));          return yield* registrations.registerDevice({ userId, payload });        }, mapRelayCommonApiErrors("invalid_dpop")),      )      .handle(        "registerLiveActivity",        Effect.fn("relay.api.mobile.registerLiveActivity")(function* (args) {          const { payload } = args;          const { userId, token } = yield* RelayClientPrincipal;          const proofKeyThumbprint = yield* requireDpopPrincipalScope("mobile:registration");          yield* requireDpopThumbprint(proofKeyThumbprint, {            expectedAccessToken: token,          }).pipe(Effect.provideService(DpopProofs.DpopProofReplay, dpopProofs));          return yield* registrations.registerLiveActivity({ userId, payload });        }, mapRelayCommonApiErrors("invalid_dpop")),      )      .handle(        "unregisterDevice",        Effect.fn("relay.api.mobile.unregisterDevice")(function* (args) {          const { params } = args;          const { userId, token } = yield* RelayClientPrincipal;          const proofKeyThumbprint = yield* requireDpopPrincipalScope("mobile:registration");          yield* requireDpopThumbprint(proofKeyThumbprint, {            expectedAccessToken: token,          }).pipe(Effect.provideService(DpopProofs.DpopProofReplay, dpopProofs));          return yield* registrations.unregisterDevice({ userId, deviceId: params.deviceId });        }, mapRelayCommonApiErrors("invalid_dpop")),      );  }),); export const clientApi = HttpApiBuilder.group(  RelayApi,  "client",  Effect.fnUntraced(function* (handlers) {    const config = yield* RelayConfiguration.RelayConfiguration;    const crypto = yield* Crypto.Crypto;    const relayTokens = yield* RelayTokens.RelayTokens;    const linker = yield* EnvironmentLinker.EnvironmentLinker;    const links = yield* EnvironmentLinks.EnvironmentLinks;    const managedEndpointProvider = yield* ManagedEndpointProvider.ManagedEndpointProvider;    const credentials = yield* EnvironmentCredentials.EnvironmentCredentials;    const devices = yield* Devices.Devices;    return handlers      .handle(        "listEnvironments",        Effect.fn("relay.api.client.listEnvironments")(function* () {          const { userId } = yield* RelayClientPrincipal;          const environments = yield* links.listForUser({ userId });          return { environments };        }, mapRelayCommonApiErrors("not_authorized")),      )      .handle(        "listDevices",        Effect.fn("relay.api.client.listDevices")(function* () {          const { userId } = yield* RelayClientPrincipal;          return { devices: yield* devices.listForUser({ userId }) };        }, mapRelayCommonApiErrors("not_authorized")),      )      .handle(        "linkEnvironment",        Effect.fn("relay.api.client.linkEnvironment")(          function* (args) {            const { payload } = args;            yield* appendRelayCredentialResponseHeaders;            const { userId } = yield* RelayClientPrincipal;            const result = yield* linker.link({ userId, request: payload });            return {              ok: true,              cloudUserId: userId,              environmentId: result.environmentId,              endpoint: result.endpoint,              endpointRuntime: result.endpointRuntime,              relayIssuer: config.relayIssuer,              environmentCredential: result.environmentCredential,              cloudMintPublicKey: config.cloudMintPublicKey,            };          },          mapErrorTags({            EnvironmentLinkProofExpired: (_error, traceId) =>              new RelayEnvironmentLinkProofExpiredError({                code: "environment_link_proof_expired",                traceId,              }),            EnvironmentLinkProofInvalid: (linkError, traceId) =>              new RelayEnvironmentLinkProofInvalidError({                code: "environment_link_proof_invalid",                reason: linkError.reason,                traceId,              }),            ManagedEndpointProvisioningNotConfigured: (_error, traceId) =>              new RelayEnvironmentLinkUnavailableError({                code: "environment_link_unavailable",                reason: "managed_endpoint_not_configured",                traceId,              }),            ManagedEndpointProvisioningFailed: (_error, traceId) =>              new RelayEnvironmentLinkUnavailableError({                code: "environment_link_unavailable",                reason: "managed_endpoint_provisioning_failed",                traceId,              }),            ManagedEndpointOriginNotAllowed: (_error, traceId) =>              new RelayEnvironmentLinkProofInvalidError({                code: "environment_link_proof_invalid",                reason: "origin_not_allowed",                traceId,              }),            EnvironmentLinkUpsertPersistenceError: (_error, traceId) =>              new RelayEnvironmentLinkFailedError({                code: "environment_link_failed",                reason: "link_persistence_failed",                traceId,              }),            EnvironmentCredentialCreatePersistenceError: (_error, traceId) =>              new RelayEnvironmentLinkFailedError({                code: "environment_link_failed",                reason: "credential_persistence_failed",                traceId,              }),            DpopProofReplayPersistenceError: (_error, traceId) =>              new RelayEnvironmentLinkFailedError({

Lines 1–500 of 1118.