import { createClerkClient, verifyToken } from "@clerk/backend"; import { describe, expect, it } from "@effect/vitest"; import { vi } from "vite-plus/test"; 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 * as Predicate from "effect/Predicate"; import * as Redacted from "effect/Redacted"; import * as Tracer from "effect/Tracer"; 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 { RelayEnvironmentAuth } from "@t3tools/contracts/relay"; import { relayCors, relayDocsRedirectRoute, relayEnvironmentAuthLayer, relayNotFoundRoute, traceRelayHttpRequestWith, verifyRelayClientBearerToken, withoutCapturedParentSpan, } from "./Api.ts"; import * as RelayConfiguration from "../Config.ts"; import * as EnvironmentCredentials from "../environments/EnvironmentCredentials.ts"; vi.mock("@clerk/backend", () => ({ createClerkClient: vi.fn(), verifyToken: vi.fn(), })); const relaySettings: RelayConfiguration.RelayConfiguration["Service"] = { relayIssuer: "https://relay.example.test", apns: { teamId: "apns-team", keyId: "apns-key", privateKey: Redacted.make("apns-private-key"), bundleId: "com.example.t3", environment: "sandbox", }, clerkSecretKey: Redacted.make("clerk-secret-key"), clerkPublishableKey: "pk_test_test", clerkJwtAudience: "t3-code-relay", apnsDeliveryJobSigningSecret: Redacted.make("apns-delivery-secret"), cloudMintPrivateKey: Redacted.make("cloud-mint-private-key"), cloudMintPublicKey: "cloud-mint-public-key", managedEndpointBaseDomain: undefined, managedEndpointNamespace: undefined, }; describe("relay client authentication", () => { it.effect("preserves the existing Clerk session JWT path", () => Effect.gen(function* () { vi.mocked(verifyToken).mockResolvedValue({ sub: "user_session", aud: relaySettings.clerkJwtAudience, } as never); expect(yield* verifyRelayClientBearerToken(relaySettings, "session-token")).toEqual({ sub: "user_session", mode: "clerk_session_bearer", }); expect(verifyToken).toHaveBeenCalledWith("session-token", { secretKey: "clerk-secret-key", audience: relaySettings.clerkJwtAudience, }); expect(createClerkClient).not.toHaveBeenCalled(); }).pipe( Effect.ensuring( Effect.sync(() => { vi.mocked(verifyToken).mockReset(); vi.mocked(createClerkClient).mockReset(); }), ), ), ); it.effect("falls back to Clerk OAuth token verification for the headless CLI", () => Effect.gen(function* () { vi.mocked(verifyToken).mockRejectedValue(new Error("not a session JWT")); vi.mocked(createClerkClient).mockReturnValue({ authenticateRequest: vi.fn().mockResolvedValue({ isAuthenticated: true, toAuth: () => ({ userId: "user_oauth" }), }), } as never); expect(yield* verifyRelayClientBearerToken(relaySettings, "oauth-token")).toEqual({ sub: "user_oauth", mode: "clerk_oauth_bearer", }); expect(createClerkClient).toHaveBeenCalledWith({ secretKey: "clerk-secret-key", publishableKey: "pk_test_test", }); }).pipe( Effect.ensuring( Effect.sync(() => { vi.mocked(verifyToken).mockReset(); vi.mocked(createClerkClient).mockReset(); }), ), ), ); }); describe("relay environment authentication", () => { it.effect("preserves credential lookup persistence failures as internal errors", () => { const failure = new EnvironmentCredentials.EnvironmentCredentialAuthenticatePersistenceError({ cause: "database unavailable", }); const credentials: EnvironmentCredentials.EnvironmentCredentials["Service"] = { create: () => Effect.die("unused create"), authenticate: () => Effect.fail(failure), revokeForEnvironmentPublicKey: () => Effect.die("unused revoke"), }; return Effect.gen(function* () { const auth = yield* RelayEnvironmentAuth; const error = yield* Effect.flip( auth.environmentBearer(Effect.succeed(HttpServerResponse.empty()), { credential: Redacted.make("environment-credential"), endpoint: {} as never, group: {} as never, }), ); expect(Predicate.isTagged(error, "RelayInternalError")).toBe(true); if (Predicate.isTagged(error, "RelayInternalError")) { expect(error.reason).toBe("persistence_failed"); } }).pipe( Effect.provideService( HttpServerRequest.HttpServerRequest, HttpServerRequest.fromWeb(new Request("https://relay.test/v1/server/link")), ), Effect.provideService(HttpServerRequest.ParsedSearchParams, {}), Effect.provideService(HttpRouter.RouteContext, { params: {}, route: {} as never, }), Effect.provide( relayEnvironmentAuthLayer.pipe( Layer.provide(Layer.succeed(EnvironmentCredentials.EnvironmentCredentials, credentials)), ), ), Effect.scoped, ); }); }); describe("relay request tracing", () => { it.effect( "does not parent endpoint spans to an ambient parent captured while building handlers", () => Effect.gen(function* () { const spans: Array = []; const tracer = Tracer.make({ span: (options) => { const span = new Tracer.NativeSpan(options); spans.push(span); return span; }, }); const ambientParent = Tracer.externalSpan({ traceId: "00000000000000000000000000000001", spanId: "0000000000000001", sampled: true, }); const endpoint = yield* withoutCapturedParentSpan( Effect.context().pipe( Effect.map((capturedContext: Context.Context) => Effect.succeed(HttpServerResponse.empty({ status: 204 })).pipe( Effect.withSpan("relay.test.endpoint"), Effect.provideContext(capturedContext), ), ), ), ).pipe(Effect.provideService(Tracer.ParentSpan, ambientParent)); const request = HttpServerRequest.fromWeb( new Request("https://relay.test/v1/mobile/devices?client=mobile", { method: "POST", headers: { authorization: "Bearer secret", dpop: "signed-proof", }, }), ); yield* traceRelayHttpRequestWith(endpoint, Layer.succeed(Tracer.Tracer, tracer)).pipe( Effect.provideService(HttpServerRequest.HttpServerRequest, request), ); expect(spans.map((span) => span.name)).toEqual(["http.server POST", "relay.test.endpoint"]); expect(spans[0]?.kind).toBe("server"); expect(spans[0]?.attributes.get("url.path")).toBe("/v1/mobile/devices"); expect(spans[0]?.attributes.get("http.response.status_code")).toBe(204); expect(spans[0]?.attributes.get("http.request.header.authorization")).toBe(""); expect(spans[0]?.attributes.get("http.request.header.dpop")).toBe(""); expect(Option.isNone(spans[0]!.parent)).toBe(true); expect(Option.getOrUndefined(spans[1]!.parent)?.spanId).toBe(spans[0]?.spanId); }), ); }); describe("relay routing fallback", () => { it.effect("redirects the relay root to the API docs", () => Effect.gen(function* () { const request = HttpServerRequest.fromWeb(new Request("https://relay.test/")); const httpEffect = yield* HttpRouter.toHttpEffect( Layer.mergeAll(relayDocsRedirectRoute, relayNotFoundRoute, relayCors), ); const response = yield* httpEffect.pipe( Effect.provideService(HttpServerRequest.HttpServerRequest, request), ); expect(response.status).toBe(302); expect(response.headers.location).toBe("/docs"); expect(response.headers["access-control-allow-origin"]).toBe("*"); }).pipe(Effect.scoped), ); it.effect("returns a CORS-compatible 404 response for unmatched paths", () => Effect.gen(function* () { const request = HttpServerRequest.fromWeb( new Request("https://relay.test/v1/environmentsd", { method: "GET" }), ); const httpEffect = yield* HttpRouter.toHttpEffect(Layer.merge(relayNotFoundRoute, relayCors)); const response = yield* httpEffect.pipe( Effect.provideService(HttpServerRequest.HttpServerRequest, request), ); expect(response.status).toBe(404); expect(response.headers["access-control-allow-origin"]).toBe("*"); }).pipe(Effect.scoped), ); });