193 lines
6.5 KiB
Markdown
193 lines
6.5 KiB
Markdown
# 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
|
|
|
|
```ts
|
|
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
|
|
|
|
```ts
|
|
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
|
|
|
|
```ts
|
|
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
|
|
|
|
```ts
|
|
type GatewayConfig, GatewayRequest, GatewayResponse, GatewayResult
|
|
type RouteDefinition, RouteMatch, Target, TargetHealth
|
|
type CircuitBreakerConfig, CircuitBreakerState, CircuitState
|
|
type BalancerStrategy, HttpMethod, RequestTransformer, ResponseTransformer
|
|
```
|
|
|
|
### Error codes
|
|
|
|
```ts
|
|
type GatewayErrorCode =
|
|
| "GATEWAY_NO_ROUTE"
|
|
| "GATEWAY_CIRCUIT_OPEN"
|
|
| "GATEWAY_UPSTREAM_TIMEOUT"
|
|
| "GATEWAY_UPSTREAM_UNREACHABLE"
|
|
| "GATEWAY_CONFIG_INVALID"
|
|
| "GATEWAY_TRANSFORM_FAILED"
|
|
```
|
|
|
|
### Constants
|
|
|
|
```ts
|
|
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
|
|
|
|
```text
|
|
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`.
|