Files
2026-05-27 23:29:53 +01:00

44 lines
2.3 KiB
Markdown

# `@suaveplan/api-tenant-resolver-subdomain` — subdomain tenant resolver
**Package**: `@suaveplan/api-tenant-resolver-subdomain`
**Status**: PROPOSED
**Type**: new-package
**Stage**: 8 — see umbrella `openspec/changes/api-plugin-foundation/`
## Why
Per design doc §6 step 4, multi-tenant deployments commonly serve each tenant at `<tenant>.api.example.com`. This adapter resolves the tenant from the request's host header, completing the v1 tenant-resolver chain alongside the header adapter.
## What changes
- ADDED: `createSubdomainTenantResolver({ baseDomain, validate, registry })` — reads `request.host` (or `X-Forwarded-Host` when configured), strips `baseDomain`, validates the remaining label, and returns `{ tenantId, source: "subdomain" }` or `null`.
- ADDED: Multi-label support — `tenantLabelIndex` config selects which label is the tenant (default 0 — leftmost). Supports nested deployments (`<tenant>.<region>.api.example.com`).
- ADDED: Forwarded-host trust — `trustForwardedHost` config defaults to `false` (don't trust client-supplied headers); when `true`, consults `trustedProxyCidrs` to validate the upstream IP.
- ADDED: Strict mode parity with `api-tenant-resolver-header`.
- ADDED: Conformance — passes `runTenantResolverConformance`.
- ADDED: Error codes (`TENANT_SUBDOMAIN_*`): `INVALID`, `NOT_FOUND_IN_REGISTRY`, `BASE_DOMAIN_MISMATCH`, `FORWARDED_HOST_UNTRUSTED`.
## Out of scope
- TLS / cert provisioning per tenant — operator concern.
- Reverse-DNS resolution — out of scope; we only look at the request host.
## 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 |
## Verification approach
- `src/resolver/resolver.test.ts` — `acme.api.example.com` → `acme`; mismatched base domain → strict raises `TENANT_SUBDOMAIN_BASE_DOMAIN_MISMATCH`; multi-label index.
- `src/forwarded/forwarded.test.ts` — trusted-proxy CIDR check; untrusted proxy ignored.
- `src/resolver/resolver.spec-conformance.test.ts` — runs `runTenantResolverConformance`.
- `tests/dep-graph.test.ts`.
## Migration impact
None — additive only. `api-host` wires this when `host.tenant.resolvers` includes `"subdomain"`.