937 lines · 36.5 KB · TypeScript
RawDownload
import { AuthStandardClientScopes, EnvironmentId } from "@t3tools/contracts";import {  RelayEnvironmentConnectScope,  type RelayEnvironmentConnectResponse,} from "@t3tools/contracts/relay";import { describe, expect, it } from "@effect/vitest";import * as Clock from "effect/Clock";import * as Deferred from "effect/Deferred";import * as Effect from "effect/Effect";import * as Fiber from "effect/Fiber";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as Queue from "effect/Queue";import * as Ref from "effect/Ref";import * as TestClock from "effect/testing/TestClock"; import { DPOP_UNKNOWN_HINT } from "../relay/errorPresentation.ts";import * as ManagedRelay from "../relay/managedRelay.ts";import { remoteHttpClientLayer } from "../rpc/http.ts";import * as ClientCapabilities from "../platform/capabilities.ts";import * as RemoteEnvironmentAuthorization from "./service.ts";import * as TokenStore from "./tokenStore.ts"; const ENVIRONMENT_ID = EnvironmentId.make("environment-1");const ENDPOINT = {  httpBaseUrl: "https://environment.example.test",  wsBaseUrl: "wss://environment.example.test",  providerKind: "cloudflare_tunnel" as const,};const DESCRIPTOR = {  environmentId: ENVIRONMENT_ID,  label: "Remote environment",  platform: {    os: "linux",    arch: "x64",  },  serverVersion: "0.0.0-test",  capabilities: {    repositoryIdentity: true,  },};const BOOTSTRAP: RelayEnvironmentConnectResponse = {  environmentId: ENVIRONMENT_ID,  endpoint: ENDPOINT,  credential: "relay-bootstrap",  expiresAt: "2026-06-06T01:00:00.000Z",}; function recordedFetch(responses: ReadonlyArray<Response>) {  const calls: Array<readonly [RequestInfo | URL, RequestInit]> = [];  let responseIndex = 0;  const fetchFn = ((input, init) => {    calls.push([input, init ?? {}]);    const response = responses[responseIndex++];    return response === undefined      ? Promise.reject(new Error(`Unexpected fetch call to ${String(input)}`))      : Promise.resolve(response);  }) satisfies typeof fetch;  return { calls, fetchFn };} const websocketTicket = (ticket: string) =>  Response.json({    ticket,    expiresAt: "2026-06-06T01:00:00.000Z",  }); const accessToken = (token: string) =>  Response.json({    access_token: token,    issued_token_type: "urn:ietf:params:oauth:token-type:access_token",    token_type: "DPoP",    expires_in: 3_600,    scope: AuthStandardClientScopes.join(" "),  }); const authInvalid = () =>  Response.json(    {      _tag: "EnvironmentAuthInvalidError",      code: "auth_invalid",      reason: "invalid_credential",      traceId: "trace-auth-invalid",    },    { status: 401 },  ); const persistedToken = (  input: {    readonly environmentId?: EnvironmentId;    readonly accessToken?: string;    readonly expiresAtEpochMs?: number;    readonly dpopThumbprint?: string;  } = {},) =>  new TokenStore.RemoteDpopAccessToken({    environmentId: input.environmentId ?? ENVIRONMENT_ID,    accountId: "account-1",    label: DESCRIPTOR.label,    endpoint: ENDPOINT,    accessToken: input.accessToken ?? "cached-access-token",    expiresAtEpochMs: input.expiresAtEpochMs ?? Number.MAX_SAFE_INTEGER,    dpopThumbprint: input.dpopThumbprint ?? "thumbprint-1",  }); const makeHarness = Effect.fn("TestRemoteAuthorization.makeHarness")(function* (input: {  readonly initialToken?: TokenStore.RemoteDpopAccessToken;  readonly responses: ReadonlyArray<Response>;  readonly bootstrap?: RelayEnvironmentConnectResponse;  readonly beforeBootstrap?: Effect.Effect<void, ManagedRelay.ManagedRelayClientError>;  readonly beforePut?: Effect.Effect<void>;  readonly clerkToken?: ClientCapabilities.CloudSession["Service"]["clerkToken"];}) {  const tokens = yield* Ref.make(    new Map(      input.initialToken === undefined        ? []        : [[input.initialToken.environmentId, input.initialToken]],    ),  );  const bootstrapCalls = yield* Ref.make(0);  const relayInputs = yield* Ref.make<    ReadonlyArray<Parameters<ManagedRelay.ManagedRelayClient["Service"]["connectEnvironment"]>[0]>  >([]);  const session = yield* Ref.make<Option.Option<ClientCapabilities.CloudSessionIdentity>>(    Option.some({ accountId: "account-1" }),  );  const thumbprint = yield* Ref.make("thumbprint-1");  const tokenReads = yield* Queue.unbounded<EnvironmentId>();  const proofInputs = yield* Ref.make<    ReadonlyArray<{      readonly method: string;      readonly url: string;      readonly accessToken?: string;    }>  >([]);  const fetch = recordedFetch(input.responses);   const tokenStore = TokenStore.RemoteDpopAccessTokenStore.of({    get: (environmentId) =>      Ref.get(tokens).pipe(        Effect.map((current) => Option.fromUndefinedOr(current.get(environmentId))),        Effect.tap(() => Queue.offer(tokenReads, environmentId)),      ),    put: (token) =>      (input.beforePut ?? Effect.void).pipe(        Effect.andThen(          Ref.update(tokens, (current) => {            const next = new Map(current);            next.set(token.environmentId, token);            return next;          }),        ),      ),    remove: (environmentId) =>      Ref.update(tokens, (current) => {        const next = new Map(current);        next.delete(environmentId);        return next;      }),  });  const signer = ManagedRelay.ManagedRelayDpopSigner.of({    thumbprint: Ref.get(thumbprint),    createProof: (proofInput) =>      Ref.update(proofInputs, (current) => [...current, proofInput]).pipe(        Effect.as(`proof:${proofInput.url}`),      ),  });  const unexpected = () => Effect.die("Unexpected relay request");  const relay = ManagedRelay.ManagedRelayClient.of({    relayUrl: "https://relay.example.test",    listEnvironments: unexpected,    listDevices: unexpected,    createEnvironmentLinkChallenge: unexpected,    linkEnvironment: unexpected,    unlinkEnvironment: unexpected,    getEnvironmentStatus: unexpected,    connectEnvironment: (request) =>      Effect.gen(function* () {        yield* Ref.update(bootstrapCalls, (count) => count + 1);        yield* Ref.update(relayInputs, (current) => [...current, request]);        yield* input.beforeBootstrap ?? Effect.void;        return input.bootstrap ?? BOOTSTRAP;      }),    registerDevice: unexpected,    unregisterDevice: unexpected,    registerLiveActivity: unexpected,    getAgentActivitySnapshot: unexpected,    resetTokenCache: Effect.void,  });  const layer = RemoteEnvironmentAuthorization.layer.pipe(    Layer.provide(      Layer.mergeAll(        remoteHttpClientLayer(fetch.fetchFn),        Layer.succeed(ManagedRelay.ManagedRelayDpopSigner, signer),        Layer.succeed(ManagedRelay.ManagedRelayClient, relay),        Layer.succeed(ClientCapabilities.CloudSession, {          identity: Ref.get(session),          clerkToken: input.clerkToken ?? Effect.succeed("clerk-session"),        }),        Layer.succeed(ClientCapabilities.RelayDeviceIdentity, {          deviceId: Effect.succeed(Option.some("device-1")),        }),        Layer.succeed(TokenStore.RemoteDpopAccessTokenStore, tokenStore),        Layer.succeed(          ClientCapabilities.ClientPresentation,          ClientCapabilities.ClientPresentation.of({            metadata: {              label: "T3 Code Test",              deviceType: "mobile",              os: "test",            },            scopes: AuthStandardClientScopes,          }),        ),      ),    ),  );  return {    layer,    tokens,    bootstrapCalls,    proofInputs,    fetch,    relayInputs,    session,    thumbprint,    tokenReads,  };}); describe("RemoteEnvironmentAuthorization", () => {  it.effect("reuses a validated bearer descriptor while issuing fresh websocket tickets", () =>    Effect.gen(function* () {      const harness = yield* makeHarness({        responses: [          Response.json(DESCRIPTOR),          websocketTicket("first-ticket"),          websocketTicket("second-ticket"),        ],      });       const [first, second] = yield* Effect.gen(function* () {        const remote = yield* RemoteEnvironmentAuthorization.RemoteEnvironmentAuthorization;        const authorize = () =>          remote.authorizeBearer({            expectedEnvironmentId: ENVIRONMENT_ID,            httpBaseUrl: ENDPOINT.httpBaseUrl,            wsBaseUrl: ENDPOINT.wsBaseUrl,            bearerToken: "bearer-token",            connectionMethod: "direct",          });        return [yield* authorize(), yield* authorize()] as const;      }).pipe(Effect.provide(harness.layer));       expect(first.socketUrl).toContain("wsTicket=first-ticket");      expect(second.socketUrl).toContain("wsTicket=second-ticket");      expect(        harness.fetch.calls.filter(([url]) => String(url).endsWith("/.well-known/t3/environment")),      ).toHaveLength(1);      expect(        harness.fetch.calls.filter(([url]) => String(url).endsWith("/api/auth/websocket-ticket")),      ).toHaveLength(2);    }),  );   it.effect("revalidates a bearer descriptor after the cache expires", () =>    Effect.gen(function* () {      const reassignedEnvironmentId = EnvironmentId.make("environment-2");      const harness = yield* makeHarness({        responses: [          Response.json(DESCRIPTOR),          websocketTicket("first-ticket"),          Response.json({            ...DESCRIPTOR,            environmentId: reassignedEnvironmentId,          }),        ],      });       const failure = yield* Effect.gen(function* () {        const remote = yield* RemoteEnvironmentAuthorization.RemoteEnvironmentAuthorization;        const authorize = () =>          remote.authorizeBearer({            expectedEnvironmentId: ENVIRONMENT_ID,            httpBaseUrl: ENDPOINT.httpBaseUrl,            wsBaseUrl: ENDPOINT.wsBaseUrl,            bearerToken: "bearer-token",            connectionMethod: "direct",          });         yield* authorize();        yield* TestClock.adjust("10 seconds");        return yield* authorize().pipe(Effect.flip);      }).pipe(Effect.provide(Layer.merge(harness.layer, TestClock.layer())));       expect(failure).toEqual(        expect.objectContaining({          _tag: "ConnectionBlockedError",          reason: "configuration",          detail: `Connected environment ${reassignedEnvironmentId} does not match ${ENVIRONMENT_ID}.`,        }),      );      expect(        harness.fetch.calls.filter(([url]) => String(url).endsWith("/.well-known/t3/environment")),      ).toHaveLength(2);    }),  );   it.effect("reuses a same-account persisted environment token without contacting the relay", () =>    Effect.gen(function* () {      const cached = new TokenStore.RemoteDpopAccessToken({        environmentId: ENVIRONMENT_ID,        accountId: "account-1",        label: DESCRIPTOR.label,        endpoint: ENDPOINT,        accessToken: "cached-access-token",        expiresAtEpochMs: Number.MAX_SAFE_INTEGER,        dpopThumbprint: "thumbprint-1",      });      const harness = yield* makeHarness({        initialToken: cached,        responses: [websocketTicket("cached-ticket")],      });       const authorized = yield* Effect.gen(function* () {        const remote = yield* RemoteEnvironmentAuthorization.RemoteEnvironmentAuthorization;        return yield* remote.authorizeDpop({          expectedEnvironmentId: ENVIRONMENT_ID,        });      }).pipe(Effect.provide(harness.layer));       expect(authorized.socketUrl).toContain("wsTicket=cached-ticket");      expect(authorized.socketUrl).toContain("connectionMethod=relay");      expect(yield* Ref.get(harness.bootstrapCalls)).toBe(0);      expect(harness.fetch.calls).toHaveLength(1);      expect(String(harness.fetch.calls[0]?.[0])).toBe(        "https://environment.example.test/api/auth/websocket-ticket",      );    }),  );   it.effect("refreshes and persists an expired environment token", () =>    Effect.gen(function* () {      const expired = new TokenStore.RemoteDpopAccessToken({        environmentId: ENVIRONMENT_ID,        accountId: "account-1",        label: DESCRIPTOR.label,        endpoint: ENDPOINT,        accessToken: "expired-access-token",        expiresAtEpochMs: 0,        dpopThumbprint: "thumbprint-1",      });      const harness = yield* makeHarness({        initialToken: expired,        responses: [          Response.json(DESCRIPTOR),          accessToken("fresh-access-token"),          websocketTicket("fresh-ticket"),        ],      });       const authorized = yield* Effect.gen(function* () {        const remote = yield* RemoteEnvironmentAuthorization.RemoteEnvironmentAuthorization;        return yield* remote.authorizeDpop({          expectedEnvironmentId: ENVIRONMENT_ID,        });      }).pipe(Effect.provide(harness.layer));       expect(authorized.socketUrl).toContain("wsTicket=fresh-ticket");      expect(yield* Ref.get(harness.bootstrapCalls)).toBe(1);      expect((yield* Ref.get(harness.tokens)).get(ENVIRONMENT_ID)).toEqual(        expect.objectContaining({          accessToken: "fresh-access-token",          dpopThumbprint: "thumbprint-1",        }),      );      expect(harness.fetch.calls).toHaveLength(3);    }),  );   it.effect("evicts an auth-invalid cached token and obtains a fresh bootstrap", () =>    Effect.gen(function* () {      const cached = new TokenStore.RemoteDpopAccessToken({        environmentId: ENVIRONMENT_ID,        accountId: "account-1",        label: DESCRIPTOR.label,        endpoint: ENDPOINT,        accessToken: "invalid-access-token",        expiresAtEpochMs: Number.MAX_SAFE_INTEGER,        dpopThumbprint: "thumbprint-1",      });      const harness = yield* makeHarness({        initialToken: cached,        responses: [          authInvalid(),          Response.json(DESCRIPTOR),          accessToken("replacement-access-token"),          websocketTicket("replacement-ticket"),        ],      });       const authorized = yield* Effect.gen(function* () {        const remote = yield* RemoteEnvironmentAuthorization.RemoteEnvironmentAuthorization;        return yield* remote.authorizeDpop({          expectedEnvironmentId: ENVIRONMENT_ID,        });      }).pipe(Effect.provide(harness.layer));       expect(authorized.socketUrl).toContain("wsTicket=replacement-ticket");      expect(yield* Ref.get(harness.bootstrapCalls)).toBe(1);      expect((yield* Ref.get(harness.tokens)).get(ENVIRONMENT_ID)).toEqual(        expect.objectContaining({          accessToken: "replacement-access-token",        }),      );      expect(harness.fetch.calls).toHaveLength(4);    }),  );   it.effect("presents clock skew as one possible cause for a generic DPoP rejection", () =>    Effect.gen(function* () {      const harness = yield* makeHarness({        responses: [Response.json(DESCRIPTOR), authInvalid()],      });       const failure = yield* Effect.gen(function* () {        const remote = yield* RemoteEnvironmentAuthorization.RemoteEnvironmentAuthorization;        return yield* remote.authorizeDpop({          expectedEnvironmentId: ENVIRONMENT_ID,        });      }).pipe(Effect.provide(harness.layer), Effect.flip);       expect(failure).toMatchObject({        _tag: "ConnectionBlockedError",        reason: "authentication",        detail: `The environment credential is invalid. ${DPOP_UNKNOWN_HINT}`,        traceId: "trace-auth-invalid",      });    }),  );   it.effect("refreshes a cached endpoint after its first transient failure", () =>    Effect.gen(function* () {      const cached = new TokenStore.RemoteDpopAccessToken({        environmentId: ENVIRONMENT_ID,        accountId: "account-1",        label: DESCRIPTOR.label,        endpoint: ENDPOINT,        accessToken: "cached-access-token",        expiresAtEpochMs: Number.MAX_SAFE_INTEGER,        dpopThumbprint: "thumbprint-1",      });      const harness = yield* makeHarness({        initialToken: cached,        responses: [          new Response("endpoint unavailable", { status: 503 }),          Response.json(DESCRIPTOR),          accessToken("replacement-access-token"),          websocketTicket("replacement-ticket"),        ],      });       const authorized = yield* Effect.gen(function* () {        const remote = yield* RemoteEnvironmentAuthorization.RemoteEnvironmentAuthorization;        return yield* remote.authorizeDpop({          expectedEnvironmentId: ENVIRONMENT_ID,        });      }).pipe(Effect.provide(harness.layer));       expect(authorized.socketUrl).toContain("wsTicket=replacement-ticket");      expect(yield* Ref.get(harness.bootstrapCalls)).toBe(1);      expect((yield* Ref.get(harness.tokens)).get(ENVIRONMENT_ID)).toEqual(        expect.objectContaining({          accessToken: "replacement-access-token",        }),      );      expect(harness.fetch.calls).toHaveLength(4);    }),  );   it.effect("removes a newly refreshed token when websocket ticket authorization fails", () =>    Effect.gen(function* () {      const harness = yield* makeHarness({        responses: [          Response.json(DESCRIPTOR),          accessToken("unusable-access-token"),          new Response("endpoint unavailable", { status: 503 }),        ],      });       yield* Effect.gen(function* () {        const remote = yield* RemoteEnvironmentAuthorization.RemoteEnvironmentAuthorization;        return yield* remote.authorizeDpop({          expectedEnvironmentId: ENVIRONMENT_ID,        });      }).pipe(Effect.provide(harness.layer), Effect.flip);       expect((yield* Ref.get(harness.tokens)).has(ENVIRONMENT_ID)).toBe(false);      expect(yield* Ref.get(harness.bootstrapCalls)).toBe(1);

Lines 1–500 of 937.