import * as NodeServices from "@effect/platform-node/NodeServices"; import { expect, it } from "@effect/vitest"; import { Duration, Effect, Layer } from "effect"; import { TestClock } from "effect/testing"; import type { ServerConfigShape } from "../../config.ts"; import { ServerConfig } from "../../config.ts"; import { SqlitePersistenceMemory } from "../../persistence/Layers/Sqlite.ts"; import { BootstrapCredentialService } from "../Services/BootstrapCredentialService.ts"; import { BootstrapCredentialServiceLive } from "./BootstrapCredentialService.ts"; const makeServerConfigLayer = ( overrides?: Partial>, ) => Layer.effect( ServerConfig, Effect.gen(function* () { const config = yield* ServerConfig; return { ...config, ...overrides, } satisfies ServerConfigShape; }), ).pipe( Layer.provide(ServerConfig.layerTest(process.cwd(), { prefix: "t3-auth-bootstrap-test-" })), ); const makeBootstrapCredentialLayer = ( overrides?: Partial>, ) => BootstrapCredentialServiceLive.pipe( Layer.provide(SqlitePersistenceMemory), Layer.provide(makeServerConfigLayer(overrides)), ); it.layer(NodeServices.layer)("BootstrapCredentialServiceLive", (it) => { it.effect("issues pairing tokens in a short manual-entry format", () => Effect.gen(function* () { const bootstrapCredentials = yield* BootstrapCredentialService; const issued = yield* bootstrapCredentials.issueOneTimeToken(); expect(issued.credential).toMatch(/^[23456789ABCDEFGHJKLMNPQRSTUVWXYZ]{12}$/); }).pipe(Effect.provide(makeBootstrapCredentialLayer())), ); it.effect("issues one-time bootstrap tokens that can only be consumed once", () => Effect.gen(function* () { const bootstrapCredentials = yield* BootstrapCredentialService; const issued = yield* bootstrapCredentials.issueOneTimeToken({ label: "Julius iPhone" }); const first = yield* bootstrapCredentials.consume(issued.credential); const second = yield* Effect.flip(bootstrapCredentials.consume(issued.credential)); expect(first.method).toBe("one-time-token"); expect(first.role).toBe("client"); expect(first.subject).toBe("one-time-token"); expect(first.label).toBe("Julius iPhone"); expect(issued.label).toBe("Julius iPhone"); expect(second._tag).toBe("BootstrapCredentialError"); expect(second.message).toContain("Unknown bootstrap credential"); }).pipe(Effect.provide(makeBootstrapCredentialLayer())), ); it.effect("atomically consumes a one-time token when multiple requests race", () => Effect.gen(function* () { const bootstrapCredentials = yield* BootstrapCredentialService; const token = yield* bootstrapCredentials.issueOneTimeToken(); const results = yield* Effect.all( Array.from({ length: 8 }, () => Effect.result(bootstrapCredentials.consume(token.credential)), ), { concurrency: "unbounded", }, ); const successes = results.filter((result) => result._tag === "Success"); const failures = results.filter((result) => result._tag === "Failure"); expect(successes).toHaveLength(1); expect(failures).toHaveLength(7); for (const failure of failures) { expect(failure.failure._tag).toBe("BootstrapCredentialError"); expect(failure.failure.message).toContain("Unknown bootstrap credential"); } }).pipe(Effect.provide(makeBootstrapCredentialLayer())), ); it.effect("seeds the desktop bootstrap credential as a one-time grant", () => Effect.gen(function* () { const bootstrapCredentials = yield* BootstrapCredentialService; const first = yield* bootstrapCredentials.consume("desktop-bootstrap-token"); const second = yield* Effect.flip(bootstrapCredentials.consume("desktop-bootstrap-token")); expect(first.method).toBe("desktop-bootstrap"); expect(first.role).toBe("owner"); expect(first.subject).toBe("desktop-bootstrap"); expect(second._tag).toBe("BootstrapCredentialError"); expect(second.status).toBe(401); }).pipe( Effect.provide( makeBootstrapCredentialLayer({ desktopBootstrapToken: "desktop-bootstrap-token", }), ), ), ); it.effect("reports seeded desktop bootstrap credentials as expired after their ttl", () => Effect.gen(function* () { const bootstrapCredentials = yield* BootstrapCredentialService; yield* TestClock.adjust(Duration.minutes(6)); const expired = yield* Effect.flip(bootstrapCredentials.consume("desktop-bootstrap-token")); expect(expired._tag).toBe("BootstrapCredentialError"); expect(expired.status).toBe(401); expect(expired.message).toContain("Bootstrap credential expired"); }).pipe( Effect.provide( Layer.merge( makeBootstrapCredentialLayer({ desktopBootstrapToken: "desktop-bootstrap-token", }), TestClock.layer(), ), ), ), ); it.effect("lists and revokes active pairing links", () => Effect.gen(function* () { const bootstrapCredentials = yield* BootstrapCredentialService; const first = yield* bootstrapCredentials.issueOneTimeToken(); const second = yield* bootstrapCredentials.issueOneTimeToken({ role: "owner" }); const activeBeforeRevoke = yield* bootstrapCredentials.listActive(); expect(activeBeforeRevoke.map((entry) => entry.id)).toContain(first.id); expect(activeBeforeRevoke.map((entry) => entry.id)).toContain(second.id); const revoked = yield* bootstrapCredentials.revoke(first.id); const activeAfterRevoke = yield* bootstrapCredentials.listActive(); const revokedConsume = yield* Effect.flip(bootstrapCredentials.consume(first.credential)); expect(revoked).toBe(true); expect(activeAfterRevoke.map((entry) => entry.id)).not.toContain(first.id); expect(activeAfterRevoke.map((entry) => entry.id)).toContain(second.id); expect(revokedConsume.message).toContain("no longer available"); expect(revokedConsume.status).toBe(401); }).pipe(Effect.provide(makeBootstrapCredentialLayer())), ); });