import { EnvironmentAuthInvalidError } from "@t3tools/contracts";import { RelayAuthInvalidError, RelayEnvironmentEndpointTimedOutError,} from "@t3tools/contracts/relay";import { describe, expect, it } from "@effect/vitest"; import { mapManagedRelayError, mapRemoteDpopEnvironmentError, mapRemoteEnvironmentError,} from "./errors.ts";import { DPOP_RETRY_HINT, DPOP_UNKNOWN_HINT } from "../relay/errorPresentation.ts";import { ManagedRelayRequestFailedError } from "../relay/managedRelay.ts";import { NETWORK_BLOCKING_HINT } from "../errors/network.ts";import { RemoteEnvironmentAuthFetchError, RemoteEnvironmentAuthTimeoutError } from "../rpc/http.ts"; describe("mapManagedRelayError", () => { it("keeps a timeout reported by the relay distinct from a local network failure", () => { const relayError = new RelayEnvironmentEndpointTimedOutError({ code: "environment_endpoint_timed_out", traceId: "trace-server-timeout", }); const mapped = mapManagedRelayError( new ManagedRelayRequestFailedError({ action: "connect relay environment", cause: relayError, relayError, }), ); expect(mapped).toMatchObject({ reason: "timeout", detail: "Relay timed out while contacting the environment endpoint.", traceId: "trace-server-timeout", }); }); it("presents clock skew as one possible cause for a generic DPoP error", () => { const mapped = mapManagedRelayError( new ManagedRelayRequestFailedError({ action: "connect relay environment", cause: new Error("request failed"), relayError: new RelayAuthInvalidError({ code: "auth_invalid", reason: "invalid_dpop", traceId: "trace-1", }), traceId: "trace-1", }), ); expect(mapped).toMatchObject({ _tag: "ConnectionBlockedError", reason: "authentication", detail: `Relay rejected the DPoP proof. ${DPOP_UNKNOWN_HINT}`, traceId: "trace-1", }); }); it("uses a neutral hint when the relay identifies a non-clock DPoP error", () => { const mapped = mapManagedRelayError( new ManagedRelayRequestFailedError({ action: "connect relay environment", cause: new Error("request failed"), relayError: new RelayAuthInvalidError({ code: "auth_invalid", reason: "invalid_dpop", dpopFailureReason: "key_mismatch", traceId: "trace-1", }), }), ); expect(mapped.message).toBe(`Relay rejected the DPoP proof. ${DPOP_RETRY_HINT}`); });}); describe("mapRemoteDpopEnvironmentError", () => { it("keeps relay descriptor auth failures distinct from DPoP proof failures", () => { const error = new EnvironmentAuthInvalidError({ code: "auth_invalid", reason: "invalid_credential", traceId: "trace-descriptor", }); expect(mapRemoteEnvironmentError(error, "relay").message).toBe( "The environment credential is invalid.", ); expect(mapRemoteDpopEnvironmentError(error).message).toBe( `The environment credential is invalid. ${DPOP_UNKNOWN_HINT}`, ); }); it.each([ new RemoteEnvironmentAuthFetchError({ message: "Failed to fetch remote environment endpoint.", cause: new TypeError("Failed to fetch"), }), new RemoteEnvironmentAuthTimeoutError("https://environment.example.test", 10_000), ])("suggests another network when the relay endpoint cannot be reached: $_tag", (error) => { const mapped = mapRemoteDpopEnvironmentError(error); expect(mapped).toMatchObject({ _tag: "ConnectionTransientError", detail: `${error.message} ${NETWORK_BLOCKING_HINT}`, }); }); it("does not present a generic environment auth error as confirmed clock skew", () => { const mapped = mapRemoteDpopEnvironmentError( new EnvironmentAuthInvalidError({ code: "auth_invalid", reason: "invalid_credential", traceId: "trace-1", }), ); expect(mapped.message).toBe(`The environment credential is invalid. ${DPOP_UNKNOWN_HINT}`); }); it("uses a neutral hint for a non-clock DPoP error from a new server", () => { const mapped = mapRemoteDpopEnvironmentError( new EnvironmentAuthInvalidError({ code: "auth_invalid", reason: "invalid_credential", dpopFailureReason: "key_mismatch", traceId: "trace-1", }), ); expect(mapped.message).toBe(`The environment credential is invalid. ${DPOP_RETRY_HINT}`); });});
import { EnvironmentAuthInvalidError } from "@t3tools/contracts";
import {
RelayAuthInvalidError,
RelayEnvironmentEndpointTimedOutError,
} from "@t3tools/contracts/relay";
import { describe, expect, it } from "@effect/vitest";
import {
mapManagedRelayError,
mapRemoteDpopEnvironmentError,
mapRemoteEnvironmentError,
} from "./errors.ts";
import { DPOP_RETRY_HINT, DPOP_UNKNOWN_HINT } from "../relay/errorPresentation.ts";
import { ManagedRelayRequestFailedError } from "../relay/managedRelay.ts";
import { NETWORK_BLOCKING_HINT } from "../errors/network.ts";
import { RemoteEnvironmentAuthFetchError, RemoteEnvironmentAuthTimeoutError } from "../rpc/http.ts";
describe("mapManagedRelayError", () => {
it("keeps a timeout reported by the relay distinct from a local network failure", () => {
const relayError = new RelayEnvironmentEndpointTimedOutError({
code: "environment_endpoint_timed_out",
traceId: "trace-server-timeout",
});
const mapped = mapManagedRelayError(
new ManagedRelayRequestFailedError({
action: "connect relay environment",
cause: relayError,
relayError,
}),
);
expect(mapped).toMatchObject({
reason: "timeout",
detail: "Relay timed out while contacting the environment endpoint.",
traceId: "trace-server-timeout",
});
});
it("presents clock skew as one possible cause for a generic DPoP error", () => {
const mapped = mapManagedRelayError(
new ManagedRelayRequestFailedError({
action: "connect relay environment",
cause: new Error("request failed"),
relayError: new RelayAuthInvalidError({
code: "auth_invalid",
reason: "invalid_dpop",
traceId: "trace-1",
}),
traceId: "trace-1",
}),
);
expect(mapped).toMatchObject({
_tag: "ConnectionBlockedError",
reason: "authentication",
detail: `Relay rejected the DPoP proof. ${DPOP_UNKNOWN_HINT}`,
traceId: "trace-1",
});
});
it("uses a neutral hint when the relay identifies a non-clock DPoP error", () => {
const mapped = mapManagedRelayError(
new ManagedRelayRequestFailedError({
action: "connect relay environment",
cause: new Error("request failed"),
relayError: new RelayAuthInvalidError({
code: "auth_invalid",
reason: "invalid_dpop",
dpopFailureReason: "key_mismatch",
traceId: "trace-1",
}),
}),
);
expect(mapped.message).toBe(`Relay rejected the DPoP proof. ${DPOP_RETRY_HINT}`);
});
});
describe("mapRemoteDpopEnvironmentError", () => {
it("keeps relay descriptor auth failures distinct from DPoP proof failures", () => {
const error = new EnvironmentAuthInvalidError({
code: "auth_invalid",
reason: "invalid_credential",
traceId: "trace-descriptor",
});
expect(mapRemoteEnvironmentError(error, "relay").message).toBe(
"The environment credential is invalid.",
);
expect(mapRemoteDpopEnvironmentError(error).message).toBe(
`The environment credential is invalid. ${DPOP_UNKNOWN_HINT}`,
);
});
it.each([
new RemoteEnvironmentAuthFetchError({
message: "Failed to fetch remote environment endpoint.",
cause: new TypeError("Failed to fetch"),
}),
new RemoteEnvironmentAuthTimeoutError("https://environment.example.test", 10_000),
])("suggests another network when the relay endpoint cannot be reached: $_tag", (error) => {
const mapped = mapRemoteDpopEnvironmentError(error);
expect(mapped).toMatchObject({
_tag: "ConnectionTransientError",
detail: `${error.message} ${NETWORK_BLOCKING_HINT}`,
});
});
it("does not present a generic environment auth error as confirmed clock skew", () => {
const mapped = mapRemoteDpopEnvironmentError(
new EnvironmentAuthInvalidError({
code: "auth_invalid",
reason: "invalid_credential",
traceId: "trace-1",
}),
);
expect(mapped.message).toBe(`The environment credential is invalid. ${DPOP_UNKNOWN_HINT}`);
});
it("uses a neutral hint for a non-clock DPoP error from a new server", () => {
const mapped = mapRemoteDpopEnvironmentError(
new EnvironmentAuthInvalidError({
code: "auth_invalid",
reason: "invalid_credential",
dpopFailureReason: "key_mismatch",
traceId: "trace-1",
}),
);
expect(mapped.message).toBe(`The environment credential is invalid. ${DPOP_RETRY_HINT}`);
});
});