1import { AuthEnvironmentMaintainScope, type ServerAuthDescriptor } from "@t3tools/contracts";
2import * as Context from "effect/Context";
3import * as Effect from "effect/Effect";
4import * as Layer from "effect/Layer";
5
6import * as ServerConfig from "../config.ts";
7import * as ServerEnvironment from "../environment/ServerEnvironment.ts";
8import { isRemoteReachableHost, resolveSessionCookieName } from "./utils.ts";
9
10export class EnvironmentAuthPolicy extends Context.Service<
11 EnvironmentAuthPolicy,
12 {
13 readonly getDescriptor: () => Effect.Effect<ServerAuthDescriptor>;
14 }
15>()("t3/auth/EnvironmentAuthPolicy") {}
16
17/** @public Service construction is part of the canonical Effect module API. */
18export const make = Effect.gen(function* () {
19 const config = yield* ServerConfig.ServerConfig;
20 const serverEnvironment = yield* ServerEnvironment.ServerEnvironmentIdentity;
21 const isRemoteReachable = isRemoteReachableHost(config.host);
22
23 const policy =
24 config.mode === "desktop"
25 ? isRemoteReachable
26 ? "remote-reachable"
27 : "desktop-managed-local"
28 : isRemoteReachable
29 ? "remote-reachable"
30 : "loopback-browser";
31
32 const bootstrapMethods: ServerAuthDescriptor["bootstrapMethods"] =
33 policy === "desktop-managed-local"
34 ? ["desktop-bootstrap"]
35 : config.mode === "desktop" && policy === "remote-reachable"
36 ? ["desktop-bootstrap", "one-time-token"]
37 : ["one-time-token"];
38
39 const descriptor: ServerAuthDescriptor = {
40 policy,
41 bootstrapMethods,
42 sessionMethods: ["browser-session-cookie", "bearer-access-token", "dpop-access-token"],
43 serverUpdateScope: AuthEnvironmentMaintainScope,
44 sessionCookieName: resolveSessionCookieName({
45 mode: config.mode,
46 port: config.port,
47 host: config.host,
48 instanceKey: config.stateDir,
49 environmentId: yield* serverEnvironment.getEnvironmentId,
50 development: config.devUrl !== undefined,
51 }),
52 };
53
54 return EnvironmentAuthPolicy.of({
55 getDescriptor: () =>
56 Effect.succeed(descriptor).pipe(Effect.withSpan("EnvironmentAuthPolicy.getDescriptor")),
57 });
58});
59
60export const layer = Layer.effect(EnvironmentAuthPolicy, make);