# `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 `SessionResolver` from `@suaveplan/api-auth/resolver` so it composes directly into `SessionResolverChain`. ## Usage: Basic ```ts 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: ```ts 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` literally rather than the wider `Promise` so type narrowing in tests can use `expectTypeOf<...>().toEqualTypeOf>()`. The chain widens it back to `Principal | null` at the boundary. - `dispose()` is a `Promise` not just any promise — the conformance harness asserts the resolved value is `undefined` so 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.