Files
suaveplan/openspec/changes/enterprise-api-gateway/proposal.md
2026-05-27 23:29:53 +01:00

6.5 KiB

OpenSpec Change: enterprise-api-gateway

  • Change ID: enterprise-api-gateway
  • Package: @suaveplan/api-gateway
  • Category: api/framework
  • Target path: api/framework/api-gateway
  • Status: PROPOSED
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/api-gateway.md

Summary

Deliver @suaveplan/api-gateway on the genesis branch from scratch at enterprise quality. The package provides a transport-agnostic API gateway layer: pattern-based Router, pluggable-strategy LoadBalancer (round-robin / random / weighted / consistent-hash), TransformerPipeline (request/response rewrite helpers), GatewayCircuitBreaker (closed → open → half-open state machine), active HealthChecker, per-route retry policy via @suaveplan/retry, rate-limiter edge hook via @suaveplan/rate-limiter, and a Hono adapter. All wired under Gateway.handle(request). Genesis adds structured errors, Zod config schemas, OTel instrumentation, @suaveplan/logger structured logging, property-based tests, and a benchmark suite.


Current-state audit (genesis)

The package does not exist on genesis yet — fresh build. Reference: /mnt/s/web/suaveplan/enterprise/api-gateway.md.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) GatewayError hierarchy
@suaveplan/types (workspace:^) LoggerLike, Clock
@suaveplan/logger (workspace:^) Per-request structured logging
@suaveplan/retry (workspace:^) Per-route retry + backoff
@suaveplan/rate-limiter (workspace:^) Gateway-edge rate limiting
@suaveplan/events (workspace:^) Circuit-breaker state-change events
@suaveplan/api (workspace:^) Hono adapter mount
hono (catalog:server) HTTP types
zod (catalog:forms) Schema validation
@opentelemetry/api (catalog:observability) Spans + metrics
tslib (catalog:build) Runtime helpers

Public API surface

Core classes and factories

function createGateway(config: GatewayConfig): Gateway
class Gateway { handle(request: GatewayRequest): Promise<GatewayResult> }
class Router { match(req: GatewayRequest): RouteMatch | null }
class LoadBalancer { select(targets: Target[], strategy: BalancerStrategy): Target }
class TransformerPipeline { run(req: GatewayRequest): GatewayRequest; runResponse(res: GatewayResponse): GatewayResponse }
class GatewayCircuitBreaker { state: CircuitState; record(success: boolean): void }

Transformer helpers

function addHeaders(headers: Record<string, string>): RequestTransformer
function addPathPrefix(prefix: string): RequestTransformer
function addResponseHeaders(headers: Record<string, string>): ResponseTransformer
function removeHeaders(names: string[]): RequestTransformer
function rewritePath(pattern: RegExp, replacement: string): RequestTransformer
function stripPathPrefix(prefix: string): RequestTransformer

Interfaces

interface IGateway { handle(request: GatewayRequest): Promise<GatewayResult> }
interface IRouter { match(req: GatewayRequest): RouteMatch | null }
interface ILoadBalancer { select(targets: Target[], strategy: BalancerStrategy): Target }
interface ITransformerPipeline { run(req: GatewayRequest): GatewayRequest }

Key types

type GatewayConfig, GatewayRequest, GatewayResponse, GatewayResult
type RouteDefinition, RouteMatch, Target, TargetHealth
type CircuitBreakerConfig, CircuitBreakerState, CircuitState
type BalancerStrategy, HttpMethod, RequestTransformer, ResponseTransformer

Error codes

type GatewayErrorCode =
  | "GATEWAY_NO_ROUTE"
  | "GATEWAY_CIRCUIT_OPEN"
  | "GATEWAY_UPSTREAM_TIMEOUT"
  | "GATEWAY_UPSTREAM_UNREACHABLE"
  | "GATEWAY_CONFIG_INVALID"
  | "GATEWAY_TRANSFORM_FAILED"

Constants

DEFAULT_BALANCER_STRATEGY, DEFAULT_FAILURE_THRESHOLD, DEFAULT_RESET_TIMEOUT
DEFAULT_SUCCESS_THRESHOLD, DEFAULT_TIMEOUT, GATEWAY_STATUS, MAX_ROUTES

Genesis additions

  1. fetcher port — GatewayConfig.fetcher: (req: GatewayRequest) => Promise<GatewayResponse> — explicit outbound HTTP call; injectable for testing.
  2. Zod schemas for GatewayConfig, RouteDefinition, CircuitBreakerConfig with createGateway parse guard.
  3. Structured GatewayError family extending SuaveplanError.
  4. OTel — span per handle() call with gateway.route, gateway.target, gateway.attempt, gateway.circuit_state attributes; gateway.requests_total counter; gateway.upstream_duration_ms histogram.
  5. @suaveplan/retry integration on RouteDefinition.retry — attempts, backoff, jitter, retryableStatuses.
  6. HealthChecker interface + default interval-based probe that updates Target.health.
  7. @suaveplan/rate-limiter hook in Gateway.handle() checked before forwarding.
  8. Hono adapter — gatewayMiddleware(gateway: IGateway): MiddlewareHandler.
  9. Property-based tests with fast-check on router, balancer, and circuit-breaker invariants.
  10. Benchmark suite measuring handle() latency.

File layout

api/framework/api-gateway/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    constants/index.ts
    types/
      common.ts
      common.md
    errors/
      gateway-errors.ts
      gateway-errors.md
      gateway-errors.test.ts
      index.ts
    schemas/
      config.schema.ts
      route.schema.ts
      circuit-breaker.schema.ts
    core/
      gateway/
        gateway.ts
        gateway.md
        gateway.types.ts
        gateway.test.ts
        index.ts
      router/
        router.ts
        router.md
        router.test.ts
        index.ts
      balancer/
        balancer.ts
        balancer.md
        balancer.test.ts
        index.ts
      transformer/
        transformer.ts
        transformer.md
        transformer.test.ts
        index.ts
      circuit-breaker/
        circuit-breaker.ts
        circuit-breaker.md
        circuit-breaker.test.ts
        index.ts
      health/
        health.ts
        health.md
        health.test.ts
        index.ts
    adapters/
      hono-adapter/
        hono-adapter.ts
        hono-adapter.md
        hono-adapter.test.ts
        index.ts
    __benchmarks__/
      gateway.bench.ts
  tests/
    integration.test.ts
    property.test.ts

Impact

Downstream: any server application that needs to proxy or compose multiple backends. Prerequisites: @suaveplan/error, @suaveplan/types, @suaveplan/logger, @suaveplan/retry, @suaveplan/rate-limiter, @suaveplan/events, @suaveplan/api.