# `options` — Zod-validated resolver options _(no submodules)_ ## Purpose Defines and validates the public option bundle accepted by `createSubdomainTenantResolver`. Every option is bounded by a Zod schema at construction time so an operator that misspells a key, supplies an invalid CIDR, or passes a negative `tenantLabelIndex` discovers the mistake immediately rather than at the first inbound request. The resolved bundle replaces every `??` ladder so the resolver body stays small and the hot-path is allocation-free. The shape mirrors `@suaveplan/api-tenant-resolver-header` / `-jwt` (id + strict + validator + registry) plus the subdomain-specific fields (`baseDomain`, `tenantLabelIndex`, `trustForwardedHost`, `trustedProxyCidrs`) and a `getTransport` extractor so the host can inject framework-specific request metadata. ## Features - Strict Zod schema — extra keys fail validation. - CIDR pre-parsing at construction time so the per-request hot-path is byte-array prefix comparison only. - Stable `INVALID_OPTIONS` code on every failure (Zod, CIDR parse, missing option object). - `LabelValidator` and `TenantRegistryLookup` opt-in extension points. ## Usage: Basic ```ts import { parseSubdomainTenantResolverOptions } from "@suaveplan/api-tenant-resolver-subdomain/options"; const resolved = parseSubdomainTenantResolverOptions({ baseDomain: "api.example.com", }); // → { id: "subdomain", baseDomain: "api.example.com", // tenantLabelIndex: 0, strict: false, ... } ``` ## Usage: Advanced ```ts import type { TenantId } from "@suaveplan/api-types/tenant"; import { parseSubdomainTenantResolverOptions } from "@suaveplan/api-tenant-resolver-subdomain/options"; const registry = new Map([ ["acme", "t_acme" as TenantId], ]); const resolved = parseSubdomainTenantResolverOptions({ id: "primary", baseDomain: "api.example.com", tenantLabelIndex: 0, strict: true, trustForwardedHost: true, trustedProxyCidrs: ["10.0.0.0/8", "2001:db8::/32"], registry: (slug) => registry.get(slug) ?? null, }); ``` ## API Reference - `SubdomainTenantResolverOptions` — public input bundle. - `ResolvedSubdomainTenantResolverOptions` — internal, every default applied, CIDRs pre-parsed. - `parseSubdomainTenantResolverOptions(input): Resolved...`. - `TenantRegistryLookup` — slug → `TenantId | null` (sync or async). - `RequestTransport` — `{ host, forwardedHost, remoteAddress }`. - `TransportExtractor` — `(request: Request) => RequestTransport`. ## Implementation Notes The schema is `.strict()` so a typo (`requirePrincipal` instead of `requireTenant`) is a hard error at construction. `validate` and `registry` are stripped before the Zod parse — `z.function()` is deprecated and unnecessary here because runtime function calls already fail loudly if the wrong shape is passed. `trustedProxyCidrs` is re-parsed through `parseCidr` so every CIDR is normalised to a `ParsedCidr` once; this is the only allocation per resolver construction (per-request matching uses the cached array).