Files
skills/docs/api-stack/api/api-tenant-resolver-header/src/validate/validate.md
2026-05-29 08:20:56 +01:00

2.8 KiB

validate

(no submodules)

Purpose

Owns the default tenant-id validator regex and the validator / registry function signatures consumed by createHeaderTenantResolver. Splitting the validator surface out of resolver.ts keeps the resolver implementation a pure orchestrator (regex check → registry probe → trust check → return) and lets hosts substitute alternative validators without monkey-patching the factory.

The default validator (^[a-z0-9-]{1,64}$) is deliberately conservative — it admits the shape of a typical slug-style identifier and rejects everything else. Hosts whose tenant ids are UUIDs, prefixed strings, or arbitrary unicode must pass an explicit validate option.

Features

  • DEFAULT_TENANT_ID_PATTERN exported as a RegExp so hosts can extend rather than re-derive (new RegExp(...|extra-form)).
  • defaultTenantIdValidator — boolean function backed by the pattern.
  • TenantIdValidator and TenantRegistryProbe type aliases so host wiring is explicit.

Usage: Basic

import { defaultTenantIdValidator } from "@suaveplan/api-tenant-resolver-header/validate";

defaultTenantIdValidator("acme"); // true
defaultTenantIdValidator("ACME"); // false (uppercase rejected)
defaultTenantIdValidator(""); // false (zero-length rejected)

Usage: Advanced

import type {
    TenantIdValidator,
    TenantRegistryProbe,
} from "@suaveplan/api-tenant-resolver-header/validate";

const uuidValidator: TenantIdValidator = (v) =>
    /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(v);

const registry: TenantRegistryProbe = async (tid) =>
    (await tenantProvider.lookup(tid as never)) !== null;

API Reference

  • const DEFAULT_TENANT_ID_PATTERN: RegExp — ^[a-z0-9-]{1,64}$.
  • const defaultTenantIdValidator: TenantIdValidator — applies the default pattern; returns boolean.
  • type TenantIdValidator = (value: string) => boolean — synchronous validator contract.
  • type TenantRegistryProbe = (tenantId: string) => boolean | Promise<boolean> — sync-or-async registry membership probe.

Implementation Notes

The validator is intentionally synchronous: the regex check is the zero-I/O happy path, and a synchronous boolean lets the resolver avoid an await micro-task in the common-case good-tenant path. Registry probes can be async because the host may back them with a real TenantProvider.lookup that hits a database; the resolver awaits the probe only after the regex check has already passed so a bad value never leaks into the registry call.

The default pattern's 64-character cap is the same maximum used by api-tenant-provider's seed schema; widening it here without widening it there would produce values the resolver accepts but the registry refuses.