1// @effect-diagnostics nodeBuiltinImport:off globalFetchInEffect:off - Exercise the real local callback receiver without contacting OpenAI.
2import { expect, it } from "@effect/vitest";
3import { EnvironmentId, ProviderInstanceId } from "@t3tools/contracts";
4import * as Deferred from "effect/Deferred";
5import * as Effect from "effect/Effect";
6import * as Fiber from "effect/Fiber";
7import * as Stream from "effect/Stream";
8import * as NodeHttp from "node:http";
9import { subscribeCodexAuthCallback } from "./CodexAuthCallback.ts";
10
11async function input() {
12 const server = NodeHttp.createServer();
13 await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
14 const address = server.address();
15 if (!address || typeof address === "string") throw new Error("address");
16 await new Promise<void>((resolve) => server.close(() => resolve()));
17 const authorizationUrl = new URL("https://auth.openai.com/api/accounts/authorize");
18 authorizationUrl.search = new URLSearchParams({
19 client_id: "dynamic_agent_client",
20 response_type: "code",
21 redirect_uri: `http://127.0.0.1:${address.port}/auth/callback`,
22 state: "a".repeat(43),
23 code_challenge_method: "S256",
24 code_challenge: "b".repeat(43),
25 }).toString();
26 return {
27 authorizationUrl: authorizationUrl.toString(),
28 returnUrl: "http://localhost:7001/welcome#agents:remote-nuc",
29 environmentId: EnvironmentId.make("remote-nuc"),
30 instanceId: ProviderInstanceId.make("work"),
31 flowId: "remote-flow",
32 };
33}
34function callback(authorizationUrl: string) {
35 const request = new URL(authorizationUrl);
36 const url = new URL(request.searchParams.get("redirect_uri")!);
37 url.search = new URLSearchParams({
38 state: request.searchParams.get("state")!,
39 code: "test-code",
40 client_id: "oaiapp_test",
41 }).toString();
42 return url;
43}
44
45it.effect("a local primary environment receives sign-in for a remote secondary environment", () =>
46 Effect.gen(function* () {
47 const request = yield* Effect.promise(input);
48 const ready = yield* Deferred.make<void>();
49 const states: string[] = [];
50 let receivedCallbackUrl: string | undefined;
51 const receiver = yield* subscribeCodexAuthCallback(request).pipe(
52 Stream.runForEach((state) =>
53 Effect.gen(function* () {
54 states.push(state.phase);
55 if (state.phase === "finished") receivedCallbackUrl = state.callbackUrl;
56 if (state.phase === "ready") yield* Deferred.succeed(ready, undefined);
57 }),
58 ),
59 Effect.forkScoped,
60 );
61 yield* Deferred.await(ready);
62 const expected = callback(request.authorizationUrl);
63 const foreign = new URL(expected);
64 foreign.searchParams.set("state", "foreign");
65 expect((yield* Effect.promise(() => fetch(foreign))).status).toBe(400);
66 const response = yield* Effect.promise(() => fetch(expected, { redirect: "manual" }));
67 expect(response.status).toBe(303);
68 expect(response.headers.get("cache-control")).toBe("no-store");
69 expect(response.headers.get("location")).toBe(request.returnUrl);
70 yield* Fiber.join(receiver);
71 expect(receivedCallbackUrl).toBe(expected.toString());
72 expect(states).toEqual(["ready", "finished"]);
73 }).pipe(Effect.scoped),
74);
75
76it.effect("disconnecting the receiving client releases the exact callback port for retry", () =>
77 Effect.gen(function* () {
78 const request = yield* Effect.promise(input);
79 const ready = yield* Deferred.make<void>();
80 const receiver = yield* subscribeCodexAuthCallback(request).pipe(
81 Stream.runForEach(() => Deferred.succeed(ready, undefined)),
82 Effect.forkScoped,
83 );
84 yield* Deferred.await(ready);
85 yield* Fiber.interrupt(receiver);
86 yield* subscribeCodexAuthCallback(request).pipe(
87 Stream.runForEach((state) =>
88 state.phase === "ready"
89 ? Effect.promise(() => fetch(callback(request.authorizationUrl), { redirect: "manual" }))
90 : Effect.void,
91 ),
92 );
93 }).pipe(Effect.scoped),
94);
95
96it.effect("the local server refuses nonlocal return destinations", () =>
97 Effect.gen(function* () {
98 const request = yield* Effect.promise(input);
99 const result = yield* subscribeCodexAuthCallback({
100 ...request,
101 returnUrl: "https://app.t3.codes/welcome",
102 }).pipe(Stream.runDrain, Effect.result);
103 expect(result._tag).toBe("Failure");
104 }),
105);