import { describe, expect, it } from "@effect/vitest"; import { EnvironmentInternalError } from "@t3tools/contracts"; import * as Cause from "effect/Cause"; import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; import * as Logger from "effect/Logger"; import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest"; import * as AuthHttp from "./http.ts"; const encodeEnvironmentInternalError = Schema.encodeUnknownSync(EnvironmentInternalError); const loggerLayer = (messages: Array) => Logger.layer( [ Logger.make(({ message }) => { messages.push(message); }), ], { mergeWithExisting: false }, ); describe("auth http diagnostics", () => { it.effect("logs and encodes bounded internal diagnostics without exposing secrets", () => { const messages: Array = []; const cause = new Error("credential=secret-value"); return Effect.gen(function* () { const error = yield* Effect.flip( AuthHttp.failEnvironmentInternal("browser_session_cookie_failed", cause), ); expect(error).toBeInstanceOf(AuthHttp.EnvironmentHttpInternalError); expect(error.failureTag).toBe("Error"); expect(error.message).toBe( "Environment API operation failed (browser_session_cookie_failed).", ); expect(encodeEnvironmentInternalError(error)).toEqual({ _tag: "EnvironmentInternalError", code: "internal_error", reason: "browser_session_cookie_failed", traceId: error.traceId, }); expect(messages).toEqual([ [ "environment api operation failed", { reason: "browser_session_cookie_failed", traceId: error.traceId, failureTag: "Error", reasonCount: 1, failureCount: 1, defectCount: 0, interruptionCount: 0, }, ], ]); }).pipe(Effect.provide(loggerLayer(messages))); }); it.effect("logs request failures without serializing their Error or Cause values", () => { const messages: Array = []; const request = HttpServerRequest.fromWeb( new Request("https://environment.example.test/api/auth/session"), ); const requestCause = Cause.combine( Cause.fail(new Error("credential=secret-value")), Cause.die(new Error("stderr=private-value")), ); return Effect.gen(function* () { const exit = yield* Effect.exit( Effect.scoped( Effect.gen(function* () { yield* AuthHttp.annotateEnvironmentRequest("auth.session"); return yield* Effect.failCause(requestCause); }), ).pipe(Effect.provideService(HttpServerRequest.HttpServerRequest, request)), ); expect(Exit.isFailure(exit)).toBe(true); expect(messages).toEqual([ [ "environment api request failed", { endpoint: "auth.session", traceId: "unavailable", failureTag: "Error", reasonCount: 2, failureCount: 1, defectCount: 1, interruptionCount: 0, }, ], ]); }).pipe(Effect.provide(loggerLayer(messages))); }); it.effect("re-propagates nested interruption causes without logging a synthetic 500", () => { const messages: Array = []; const interruption = Cause.interrupt(); const cause = new Error("cancelled", { cause: interruption }); return Effect.gen(function* () { const exit = yield* Effect.exit(AuthHttp.failEnvironmentInternal("internal_error", cause)); expect(Exit.isFailure(exit)).toBe(true); if (Exit.isFailure(exit)) { expect(Cause.hasInterruptsOnly(exit.cause)).toBe(true); expect(Option.isNone(Cause.findErrorOption(exit.cause))).toBe(true); } expect(messages).toEqual([]); }).pipe(Effect.provide(loggerLayer(messages))); }); });