# `options` — Zod-validated options for `createStaticPrincipalResolver` _(no submodules)_ ## Purpose Owns the runtime contract between the test harness call site and the resolver factory. The schema validates both the outer options bag (`{ principal, nullForPaths?, applyTo? }`) and the nested `Principal` shape (non-empty `id`, readonly `scopes`, optional `tenantId`, default-`{}` `claims`). On failure it raises a typed `AuthStaticPrincipalError` carrying the originating Zod issues — splitting between `INVALID_OPTIONS` (anything outside `principal`) and `INVALID_PRINCIPAL` (anything inside it). This module is the only place the package touches Zod at runtime. Keeping it isolated lets the resolver factory stay a thin three-line function and lets the conformance test target the resolver behaviour without invoking schema side-effects. ## Features - Strict outer schema — unknown keys at the top level reject with `INVALID_OPTIONS`. - Discriminated error codes: `principal` issues map to `INVALID_PRINCIPAL`; everything else maps to `INVALID_OPTIONS`. - Pre-flight type check rejects non-object inputs with `INVALID_OPTIONS` before Zod sees them — a cleaner message than the Zod default for `null` / arrays. - `claims` defaults to `{}` so callers don't have to write `claims: {}` for the common case. ## Usage: Basic ```ts import { parseStaticPrincipalResolverOptions } from "@suaveplan/api-auth-static-principal/resolver"; const opts = parseStaticPrincipalResolverOptions({ principal: { id: "u_1", scopes: ["billing:write"], tenantId: "acme", claims: { email: "user@acme.test" }, }, }); ``` ## Usage: Advanced Validate options that include both `applyTo` and `nullForPaths`: ```ts import { parseStaticPrincipalResolverOptions } from "@suaveplan/api-auth-static-principal/resolver"; const opts = parseStaticPrincipalResolverOptions({ principal: { id: "u_1", scopes: [], claims: {} }, nullForPaths: ["/webhooks/*", "/healthz"], applyTo: (req) => !req.headers.has("x-skip-auth"), }); ``` ## API Reference | Symbol | Kind | Description | | -------------------------------------------- | -------- | ----------------------------------------------------------------- | | `StaticPrincipalResolverOptionsSchema` | Zod | Strict object schema for the outer bag. | | `parseStaticPrincipalResolverOptions(raw)` | function | Returns the validated options or throws `AuthStaticPrincipalError`. | ## Implementation Notes The pre-flight `typeof`/`Array.isArray` check lets the function return a single canonical error for "you handed me something that isn't an object" — Zod's own behaviour on `null` is to emit `{ code: "invalid_type", expected: "object" }`, which is correct but verbose. Splitting into a pre-flight + Zod pass is one extra branch but keeps the caller-facing failure message stable. `claims` is recorded as `z.record(z.unknown())` so any free-form JWT/claims payload validates. Coercing to readonly happens at the TypeScript boundary (`StaticPrincipalResolverOptions`), not in Zod — Zod's `.readonly()` is type-level only and would re-wrap arrays at runtime unnecessarily.