3.4 KiB
3.4 KiB
resolver — createAnonymousResolver
(no submodules)
Purpose
Factory for the trivial SessionResolver that always returns null. This is
the canonical tail-of-chain resolver every public-API host configures: it
makes the "no auth" choice explicit in host.json and lets the rest of the
host (RBAC gate, error envelope, OpenAPI emission) operate uniformly because
principal is null not undefined. The factory shape exists — rather than
exposing a constant — so future option flags (e.g. logAnonymousAccess) can
be threaded in without a breaking surface change.
Features
- Always resolves
null— no header inspection, no network I/O, no state. - Idempotent
dispose()no-op (resolver holds no resources). - Strict zod options schema rejects non-object input and unknown keys with
AUTH_ANON.INVALID_OPTIONS. - Returned type is
SessionResolverfrom@suaveplan/api-auth/resolverso it composes directly intoSessionResolverChain.
Usage: Basic
import { createAnonymousResolver } from "@suaveplan/api-auth-anonymous/resolver";
const resolver = createAnonymousResolver();
// Inside a request pipeline:
const principal = await resolver.resolve(request); // → null
await resolver.dispose(); // safe to call again
Usage: Advanced
Compose as the tail of a resolver chain so a JWT-typed resolver runs first
and the anonymous resolver supplies the null short-circuit for unrecognised
requests on public routes:
import { SessionResolverChain } from "@suaveplan/api-auth";
import { createAnonymousResolver } from "@suaveplan/api-auth-anonymous/resolver";
const chain = new SessionResolverChain([
jwtResolver, // recognises Bearer tokens, else returns null
apiKeyResolver, // recognises x-api-key, else returns null
createAnonymousResolver(), // tail: always null
]);
const principal = await chain.resolve(request);
// principal is now `Principal | null`. The host applies its `publicRoutes`
// decision: a non-public route 401s; a public route proceeds with null.
API Reference
| Symbol | Kind | Description |
|---|---|---|
createAnonymousResolver |
function | (opts?: AnonymousResolverOptions) => SessionResolver. |
AnonymousResolverOptions |
type | Reserved-for-future-flags options bag. |
Implementation Notes
- The resolver returns
Promise<null>literally rather than the widerPromise<Principal | null>so type narrowing in tests can useexpectTypeOf<...>().toEqualTypeOf<Promise<null>>(). The chain widens it back toPrincipal | nullat the boundary. dispose()is aPromise<void>not just any promise — the conformance harness asserts the resolved value isundefinedso this is load-bearing.- The factory is the public surface (not a const) because future flags must
be addable without a breaking change to call sites. Even today, passing
{}is the canonical call. - No OTel instrumentation is emitted from this resolver. Anonymous-access
observability lives at the host layer (per-request span tag) — adding
counters here would force a foundation-tier package to depend on
@suaveplan/opentelemetry, which is undesirable for a hot path.