3.3 KiB
Capability Spec Delta: api-tenant-resolver-header (api-tenant-resolver-header)
Package: @suaveplan/api-tenant-resolver-header
Status: PROPOSED
Every requirement below carries a
**Verified by:**line at authoring time.
ADDED Requirements
Requirement: Resolves tenant from configured header
The package SHALL expose createHeaderTenantResolver({ headerName, validate, registry }) that reads headerName (default X-Tenant-Id) and returns { tenantId, source: "header" } when the value validates AND (when registry is supplied) is a member of the tenant registry.
Scenario: well-formed header resolves
- WHEN a request carries
X-Tenant-Id: acmeANDacmeis in the registry - THEN the resolver returns
{ tenantId: "acme", source: "header" }ANDapi.tenant.resolves_total{resolver="header"}increments
Verified by: src/resolver/resolver.test.ts::"well-formed header resolves"
Requirement: Strict mode behaviour for invalid values
The package SHALL react to invalid header values per strict config: when strict: true, raise TENANT_HEADER_INVALID (HTTP 400). When strict: false, return null so a downstream resolver may match.
Scenario: strict raises 400
- WHEN the header value fails the validator AND
strict: true - THEN the resolver raises
TENANT_HEADER_INVALID
Scenario: non-strict returns null
- WHEN the header value fails the validator AND
strict: false - THEN the resolver returns
null
Verified by: src/resolver/resolver.test.ts::"strict mode raises 400 on invalid" AND src/resolver/resolver.test.ts::"non-strict mode returns null on invalid"
Requirement: Trusted-source enforcement
The package SHALL ignore the header when request.metadata.source is not in trustedSources (default ["service-mesh"]). When ignored AND strict: true, raise TENANT_HEADER_UNTRUSTED_SOURCE; when ignored AND strict: false, return null.
Scenario: untrusted source raises in strict
- WHEN the header is present AND
request.metadata.source = "edge"ANDtrustedSources = ["service-mesh"]ANDstrict: true - THEN the resolver raises
TENANT_HEADER_UNTRUSTED_SOURCE
Verified by: src/trust/trust.test.ts::"untrusted source raises in strict mode"
Requirement: Not-found-in-registry distinct from invalid
The package SHALL distinguish a tenant that fails validation (TENANT_HEADER_INVALID) from one that is well-formed but not in the registry (TENANT_HEADER_NOT_FOUND_IN_REGISTRY). Both surface in strict mode; both return null in non-strict mode.
Scenario: well-formed but unknown tenant
- WHEN the header is
X-Tenant-Id: unknown-tenant-1AND the registry does not contain it ANDstrict: true - THEN the resolver raises
TENANT_HEADER_NOT_FOUND_IN_REGISTRY
Verified by: src/resolver/resolver.test.ts::"well-formed but unknown raises NOT_FOUND_IN_REGISTRY in strict"
Requirement: Passes runTenantResolverConformance
The package SHALL pass the conformance harness exported by @suaveplan/api-tenant-provider/testing.
Scenario: conformance passes
- WHEN
runTenantResolverConformance("header", makeHeaderResolver)runs - THEN every harness
it(...)passes
Verified by: src/resolver/resolver.spec-conformance.test.ts::"header resolver passes runTenantResolverConformance"