# `@suaveplan/api-tenant-resolver-header` — header-based tenant resolver **Package**: `@suaveplan/api-tenant-resolver-header` **Status**: PROPOSED **Type**: new-package **Stage**: 8 — see umbrella `openspec/changes/api-plugin-foundation/` ## Why Per design doc §6 step 4, the per-request pipeline runs a tenant resolver chain — first the principal's `tenantId`, then fallback resolvers. Service-to-service traffic frequently carries the tenant in an HTTP header (`X-Tenant-Id`, `X-Acme-Tenant`, etc.) because no end-user session exists to resolve it from. This adapter handles that case. ## What changes - ADDED: `createHeaderTenantResolver({ headerName, validate, registry })` — implements the `TenantResolver` contract from `api-types`. Reads `headerName` (default `X-Tenant-Id`); validates the value via the supplied `validate` function (default: must match `^[a-z0-9-]{1,64}$`) AND optionally checks membership in `tenant.provider`'s registry; resolves to `{ tenantId, source: "header" }` or `null`. - ADDED: Strict mode — when `strict: true` (host config), a value that fails validation raises `TENANT_HEADER_INVALID` (HTTP 400). When `strict: false`, invalid values cause the resolver to return `null` so a downstream resolver may match. - ADDED: Trusted-source enforcement — `trustedSources` config (default: `["service-mesh"]`) lists which traffic sources are allowed to set the header. The resolver consults `request.metadata.source` (set by upstream middleware); if the source is not trusted, the header is ignored. This prevents end-user clients from spoofing the tenant. - ADDED: Conformance — passes `runTenantResolverConformance` from `api-tenant-provider/testing`. - ADDED: Error codes (`TENANT_HEADER_*`): `INVALID`, `NOT_FOUND_IN_REGISTRY`, `UNTRUSTED_SOURCE`. ## Out of scope - The trusted-source metadata itself — set by the router adapter when traffic enters from a service mesh / mTLS-verified ingress. - Resolving multiple tenants (multi-tenant batch operations) — outside the per-request model. ## Source mapping Genesis-original. Source of design intent: `docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md`. | Requirement | Design doc section | |---|---| | Tenant resolver chain | §6 step 4 | | Service-to-service tenant injection | §6 step 4 | ## Verification approach - `src/resolver/resolver.test.ts` — valid header → tenantId; invalid + strict → 400; invalid + non-strict → null; missing header → null. - `src/trust/trust.test.ts` — untrusted source ignored even when header is well-formed; trusted source resolves. - `src/resolver/resolver.spec-conformance.test.ts` — runs `runTenantResolverConformance`. - `tests/dep-graph.test.ts` — runtime deps. ## Migration impact None — additive only. `api-host` wires this into the tenant-resolver chain when `host.tenant.resolvers` includes `"header"`.