Gateway API v1.5.1 · Experimental channel AI Gateway

CitoRoute

A Kubernetes Gateway API implementation written in Rust: kube-rs control plane, Cloudflare Pingora data plane, per-Gateway proxy workloads, a GAMMA service-mesh sidecar for east-west routing, and an AI Gateway for LLM traffic — routing OpenAI, Anthropic, and Amazon Bedrock behind a unified /v1/chat/completions API with JWT-based consumer identity and weighted backend selection. Conformance run 2026-04-26 · controller/proxy v0.3.0 · the upstream Go test harness reports PASS in 3 min 26 sec with 125 top-level tests passed (471 sub-tests) and 0 failures across the three declared profiles (GATEWAY-HTTP, GATEWAY-GRPC, MESH-HTTP) plus the TLSRoute test set, which is exercised through the TLSRoute, TLSRouteModeTerminate, and TLSRouteModeMixed features.

What is CitoRoute?

CitoRoute is a 100 % Rust implementation of the Kubernetes Gateway API (gateway.networking.k8s.io) — the official successor to Ingress. It ships an opinionated stack: a control plane built on kube-rs and an L7 data plane built on Cloudflare Pingora, with tokio-rustls and raw tokio sockets handling the TLSRoute Passthrough, Terminate, and Mixed planes.

The entire codebase is written by AI coding agents working under human direction and review — an experiment in building production-grade infrastructure software through human–AI collaboration.

Architecture at a glance

Control plane

  • Single Rust controller binary (kube-rs + kube-runtime)
  • Server-Side Apply for every generated resource
  • Watches: Gateway, GatewayClass, HTTPRoute, GRPCRoute, TLSRoute, ListenerSet, ReferenceGrant, BackendTLSPolicy, JWTValidationPolicy, LLMBackend, LLMRoute, Consumer, Service, EndpointSlice, Secret, ConfigMap
  • Emits a TOML config (one ConfigMap per Gateway) consumed by the proxy via a mounted volume
  • GatewayClass name: citoroute

Data plane

  • One Pingora-based proxy Deployment per Gateway, in the Gateway's own namespace
  • HTTP / HTTPS / h2c / WebSocket served by Pingora's ProxyHttp
  • TLSRoute Passthrough: SNI peek → tokio::io::copy_bidirectional shovel
  • TLSRoute Terminate: tokio-rustls::TlsAcceptor, hot-swappable ServerConfig via ArcSwap
  • TLSRoute Mixed: per-port unified L4 dispatcher multiplexing Passthrough + Terminate by SNI
  • Hot-reloaded routes via ArcSwap — no proxy restarts on config change

Service mesh (GAMMA)

  • Mutating admission webhook (citoroute-webhook) injects a Pingora sidecar + iptables init container
  • Egress on :15001 via SO_ORIGINAL_DST, inbound passthrough on :15006
  • Per-namespace citoroute-mesh ConfigMap indexes every HTTPRoute with parentRef.kind = Service
  • Sub-second hot-reload via direct kube-rs watch (falls back to a 500 ms file poll)

Policy & extension

  • BackendTLSPolicy (CA + SAN validation, SPIFFE/URI, conflict resolution)
  • JWTValidationPolicy (citoroute.io/v1alpha1) — direct policy attachment to Gateway per GEP-713
  • ListenerSet for additional listeners attached to a Gateway
  • ReferenceGrant enforced for every cross-namespace reference (Secrets, Services, CA ConfigMaps)

AI Gateway

  • Three CRDs: LLMBackend, Consumer, LLMRoute (citoroute.io/v1alpha1)
  • Unified /v1/chat/completions API — clients speak OpenAI protocol, the proxy translates to each provider natively
  • Providers: OpenAI, Anthropic Messages, Amazon Bedrock Converse
  • Streaming SSE for all providers (Bedrock smithy event-stream → OpenAI-style SSE)
  • AWS SigV4 signing for Bedrock (IAM keys in Secret or default credential chain)
  • JWT-based Consumer identity with claim matching & per-route authorization
  • Weighted backend selection across multiple LLMBackend resources

Conformance summary · v1.5.1

CitoRoute is run through the official upstream Gateway API conformance suite at version v1.5.1 (Experimental channel) in a single in-cluster run completed on 2026-04-26. This run includes the AI Gateway code (LLMBackend, Consumer, LLMRoute CRDs and proxy logic). The Go test harness reports PASS with no failures.

In Gateway API terminology, an implementation is "conformant" for a profile when (a) every Core test passes and (b) every Extended feature it declares in --supported-features passes. Implementations are free not to declare individual Extended features; undeclared features are auto-skipped and don't affect conformance. CitoRoute exercises two architecturally distinct stacks against this suite:

The two are summarised separately below to avoid implying that a single number covers both stacks.

Gateway profiles · per-Gateway proxy

107Top-level tests passed
396Sub-tests passed
0Failures
37Extended features declared & passing (unique across HTTPRoute / GRPCRoute / TLSRoute)
Profile Core Standard Extended Experimental Total (top-level · sub-tests) Failed Skipped
GATEWAY-HTTP 34 / 34 45 / 45 10 / 10 89 passed · 342 sub-tests 0 0
GATEWAY-GRPC 4 / 4 1 / 1 5 passed · 25 sub-tests 0 0
TLSRoute (Passthrough + Terminate + Mixed) 8 / 8 2 / 2 1 / 1 13 passed · 29 sub-tests 0 0

Across the three Gateway profiles every Core test passes, every Extended feature published in v1.5 is declared, and every declared feature passes. The 37 count is the de-duplicated set of Extended features we declare across the three route types: 25 HTTPRoute-specific (3xx redirects, H2C / WebSocket, CORS, request mirroring, timeouts, rewrites, header modifications, method / query / path matching, BackendTLSPolicy + SAN validation, …) + 2 TLSRoute-specific (TLSRouteModeTerminate, TLSRouteModeMixed) + 1 GRPCRoute-specific (the GRPCRoute profile itself) + 9 Gateway-* features shared across all three route types (address-empty, port 8080, listener isolation, infrastructure propagation, static addresses, frontend client certificate validation + insecure fallback, backend client certificate, misdirected-request detection) + 1 ListenerSet shared across all three. Per-route, that maps to the same 35 / 10 / 12 column counts shown on the upstream v1.5 comparison for HTTPRoute, GRPCRoute and TLSRoute respectively (with shared features counted once per table). The TLSRoute total above includes two early-returning NotSupported tests (TLSRouteListenerTerminateNotSupported and TLSRouteListenerMixedTerminationNotSupported) that the harness reports as PASS once the corresponding modes are declared — the active TLSRoute test set is 8 + 2 + 1 = 11.

The harness also logs one auto-skip for a single UDPRoute test ("suite does not support UDPRoute"). UDPRoute is an Alpha L4 resource in gateway.networking.k8s.io/v1alpha2 that is not part of the v1.5 Standard / Experimental channel and is not graded on the v1.5 implementations comparison. CitoRoute does not implement it and no v1.5 conformance profile depends on it.

Mesh profile · sidecar

18Top-level tests passed
75Sub-tests passed
0Failures
4Tests opted out (--skip-tests)
7 / 9Mesh-specific Extended features declared & passing
Profile Mesh Core Mesh Extended (declared) Total (top-level · sub-tests) Failed Skipped
MESH-HTTP 9 / 9 9 / 9 declared (7 mesh-specific + 2 gateway-shared) 18 passed · 75 sub-tests 0 4 opt-outs

Mesh Core is fully covered. Two mesh-specific Extended features are intentionally not declaredMeshClusterIPMatching (sidecar implements it but a separate Service-attribute validation is still pending) and MeshConsumerRoute (cross-namespace parentRef.kind=Service, not yet wired to ReferenceGrant). Four upstream tests are listed in --skip-tests for known sidecar limitations or a broken upstream test: MeshConsumerRoute, MeshFrontendHostname, MeshGRPCRouteWeight, and MeshHTTPRoute307Redirect (see Mesh profile below).

How CitoRoute compares to other implementations

The authoritative ranking lives on the official Gateway API v1.5 implementations comparison page, which aggregates the Extended-feature coverage from every submitted report and is updated as new submissions land. Rather than mirror that table here (and risk it going stale), this page only summarises CitoRoute's own position in it — and only for the three Gateway profiles, since the official Mesh table currently lists no v1.5 entries.

On a snapshot of that page taken on 2026-04-26, CitoRoute is one of only two v1.5 submissions to declare and pass every published Extended feature for the three Gateway profiles — HTTPRoute 35 / 35, GRPCRoute 10 / 10, and TLSRoute 12 / 12, with zero skipped tests in those profiles. The other project at that level is agentgateway; the next tier is envoy-gateway at 33–34, 8–9, and 10–11 respectively (with several tests skipped), followed by kgateway, nginx-gateway-fabric, traefik, microgateway, haproxy-ingress, and gke-gateway with progressively narrower feature sets.

CitoRoute additionally submits a MESH-HTTP profile from a separate sidecar binary — not directly comparable to the Gateway-profile numbers above, and with the caveats noted in the Mesh section.

Comparison summary captured 2026-04-26 — the upstream page may have changed since. Always refer to the live comparison for the current state of the ecosystem.

Stack 1 Gateway profiles · per-Gateway proxy

The three cards below cover the north-south stack: a Pingora-based proxy Deployment per Gateway resource, sharing one HTTP/2 engine across HTTPRoute, GRPCRoute, and the TLSRoute Passthrough / Terminate / Mixed planes. Every Extended feature published for these three profiles in v1.5 is declared and passing — the per-profile feature tables list them individually.

Gateway profile · HTTPRoute

Per-feature view using the same column layout as the official comparison table. CitoRoute declares and passes every one of the 35 Extended features published for HTTPRoute in v1.5.

supported & passing

Project Extended features Core Backend TLS Policy Backend TLS Policy SAN Validation Gateway Address Empty Gateway Backend Client Certificate Gateway Frontend Client Certificate Validation Gateway Frontend Client Certificate Validation Insecure Fallback Gateway HTTP Listener Isolation Gateway HTTPS Listener Detect Misdirected Requests Gateway Infrastructure Propagation Gateway Port 8080 Gateway Static Addresses HTTPRoute 303R Status Code HTTPRoute 307R Status Code HTTPRoute 308R Status Code HTTPRoute Backend Protocol H2C HTTPRoute Backend Protocol WebSocket HTTPRoute Backend Request Header Modification HTTPRoute Backend Timeout HTTPRoute CORS HTTPRoute Destination Port Matching HTTPRoute Host Rewrite HTTPRoute Method Matching HTTPRoute Named Route Rule HTTPRoute Parent Ref Port HTTPRoute Path Redirect HTTPRoute Path Rewrite HTTPRoute Port Redirect HTTPRoute Query Param Matching HTTPRoute Request Mirror HTTPRoute Request Multiple Mirrors HTTPRoute Request Percentage Mirror HTTPRoute Request Timeout HTTPRoute Response Header Modification HTTPRoute Scheme Redirect Listener Set
citoroute v0.3.0 35 / 35

Gateway profile · GRPCRoute

CitoRoute translates gRPC service/method matching to HTTP/2 path matching and reuses the same Pingora HTTP/2 stack. Every Extended Gateway feature declared for HTTPRoute also runs against GRPCRoute, plus GRPCRouteNamedRouteRule. All 10 Extended features published for GRPCRoute in v1.5 pass.

Project Extended features Core Gateway Address Empty Gateway Backend Client Certificate Gateway Frontend Client Certificate Validation Gateway Frontend Client Certificate Validation Insecure Fallback Gateway HTTP Listener Isolation Gateway HTTPS Listener Detect Misdirected Requests Gateway Infrastructure Propagation Gateway Port 8080 Gateway Static Addresses Listener Set
citoroute v0.3.0 10 / 10

Gateway profile · TLSRoute

CitoRoute implements all three TLSRoute modes defined by Gateway API v1.5.1: Passthrough (Core), Terminate (Standard Extended), and Mixed (Experimental). The proxy uses tokio SNI peeking for Passthrough, tokio-rustls for Terminate, and a buffered-ClientHello dispatcher for Mixed — all three behind the same dynamic-bind machinery used by the HTTPS listener.

Project Extended features Core Gateway Address Empty Gateway Backend Client Certificate Gateway Frontend Client Certificate Validation Gateway Frontend Client Certificate Validation Insecure Fallback Gateway HTTP Listener Isolation Gateway HTTPS Listener Detect Misdirected Requests Gateway Infrastructure Propagation Gateway Port 8080 Gateway Static Addresses Listener Set TLSRoute Mode Mixed TLSRoute Mode Terminate
citoroute v0.3.0 12 / 12

Stack 2 · separate Mesh profile · sidecar (GAMMA)

The mesh profile is served by an entirely different binary mode and codepath: a per-pod Pingora sidecar injected by an admission webhook (citoroute-webhook), with egress on :15001 via SO_ORIGINAL_DST and inbound passthrough on :15006. None of the per-Gateway proxy results above carry over — mesh has its own feature coverage, its own caveats, and its own list of not-yet-implemented features.

MESH-HTTP profile

CitoRoute submits a MESH-HTTP profile against the same upstream conformance suite, run against the injected sidecar. The official v1.5 implementations comparison currently lists no projects under the Mesh HTTPRoute section, so there is no peer to compare against here.

What passes

Tier Result Notes
Mesh Core (Mesh feature) 9 / 9 tests, 29 sub-tests Every mandatory east-west test passes
Mesh-specific Extended (declared) 7 / 7 tests, 44 sub-tests All declared mesh-specific Extended features pass
Gateway-shared Extended (303 / 308 redirects) 2 / 2 tests, 2 sub-tests Inherited from the same redirect plumbing
Total passing 18 tests, 75 sub-tests, 0 failures

The seven mesh-specific Extended features that are declared and pass:

What is not covered

Two published mesh-specific Extended features are intentionally not declared in --supported-features, and four upstream tests are listed in --skip-tests. Conformance terminology treats undeclared features as auto-skipped (they don't fail the run), but they are still gaps a reader should know about.

Item Status Reason
MeshClusterIPMatching (Extended feature) not declared Sidecar already matches by ClusterIP via SO_ORIGINAL_DST, but the upstream test asserts an additional Service attribute that needs a separate validation pass before we declare the feature
MeshConsumerRoute (Extended feature) not declared & opted out Cross-namespace HTTPRoute.parentRef.kind=Service not implemented; sidecar rejects with Accepted=False / NotAllowedByListeners until ReferenceGrant support lands
MeshFrontendHostname (test) opted out Sidecar matches by ClusterIP, not by Host header
MeshGRPCRouteWeight (test) opted out Sidecar is HTTP-only today; no gRPC-mesh path yet
MeshHTTPRoute307Redirect (test) opted out 307 redirect itself works (gateway test HTTPRoute307Redirect passes) — the upstream mesh test is broken: it references the 303 manifest, so no implementation can satisfy its 307 assertion in v1.5.1

Several other mesh tests (MeshHTTPRouteRequestMirror, MeshHTTPRouteRequestMultipleMirrors, MeshHTTPRouteRequestPercentageMirror, MeshHTTPRouteTimeoutRequest, MeshHTTPRouteTimeoutBackendRequest, MeshHTTPRouteCORS, MeshBackendTLSPolicy, MeshBackendTLSPolicySANValidation) are also listed defensively in --skip-tests as not-yet-implemented in the sidecar. They do not exist in the v1.5.1 suite yet, so they don't appear in the run output, but they document scope that the sidecar does not cover today.

Stack 3 AI Gateway · LLM routing

The AI Gateway extends CitoRoute with three custom CRDs (citoroute.io/v1alpha1) that let teams expose LLM providers behind a unified OpenAI-compatible API. Clients send standard /v1/chat/completions requests; the proxy translates to each provider’s native protocol, manages credentials, and enforces consumer-level access control.

AI Gateway features

Supported LLM providers

OpenAI Chat completions API · Bearer token auth · streaming SSE
Anthropic Messages API · x-api-key auth · automatic body translation from OpenAI format · streaming SSE
Amazon Bedrock Converse / ConverseStream API · AWS SigV4 signing (IAM keys in Secret or default credential chain) · smithy event-stream → OpenAI-style SSE

Custom Resource Definitions

CRD Purpose Key fields
LLMBackend One provider + model + endpoint + credentials provider, model, endpoint, credentialsRef, timeout, bedrock.region
Consumer Map a JWT claim key/value to a named identity jwtClaimMatch.key, jwtClaimMatch.value
LLMRoute Bind Gateway parents, consumers, and backends parentRefs[], consumerRefs[], path, backendRefs[] (with weight)

Capabilities

  • Unified client protocol — clients always use OpenAI chat completions format; the proxy translates to Anthropic Messages and Bedrock Converse natively
  • Streaming — SSE for all three providers; Bedrock smithy event-stream is decoded and re-emitted as OpenAI-style SSE chunks
  • Weighted backend selection — distribute traffic across multiple LLMBackend resources with configurable weights
  • Configurable path matchingPathPrefix or Exact match (default: /v1/chat/completions)
  • JWT-based consumer identity — validated JWT claims are matched to Consumer resources; LLMRoute.consumerRefs controls which consumers may use each route
  • Open routes — omit consumerRefs for public LLM endpoints (no JWT required)
  • AWS SigV4 signing — Bedrock requests are signed using static IAM credentials from a Kubernetes Secret or the pod’s default AWS credential chain (IRSA, instance profile)
  • Observabilitycitoroute_llm_requests_total and citoroute_llm_tokens_total Prometheus metrics with consumer, backend, model, and provider labels

Request flow

ClientGateway listener ⟶ JWT validation (if JWKS configured) ⟶ LLMRoute path match ⟶ Consumer identity check ⟶ weighted LLMBackend selection ⟶ protocol translation & credential injection ⟶ upstream provider (OpenAI / Anthropic / Bedrock) ⟶ response translation to OpenAI format ⟶ Client

Example: multi-provider setup

A single LLMRoute can reference multiple LLMBackend resources with different providers and weights. Combined with Consumer resources, teams can be isolated to specific routes while sharing the same Gateway listener:

Route path Consumers Backends Behaviour
/v1/chat/completions team-alpha, team-beta OpenAI (weight 3) + Anthropic (weight 1) 75/25 weighted split, JWT required
/llm/bedrock team-alpha Bedrock (weight 1) Bedrock-only, SigV4 signed, single team
/ai/chat (Exact) none (public) OpenAI (weight 1) Open route, no JWT needed

Test environment

Conformance is executed as an in-cluster Kubernetes Job — the upstream conformance-test Go binary running with cluster-admin RBAC against a clean Minikube node.

ClusterMinikube v1.35.1, single-node
Architectureaarch64 (Apple Silicon)
Resources4 vCPU · 6 GiB RAM
Gateway API CRDsv1.5.1, Experimental channel
Conformance suitekubernetes-sigs/gateway-api conformance v1.5.1
Conformance image tag20260426092159
Controller / proxy image tag20260426091613 (citoroute v0.3.0, includes AI Gateway)
ProfilesGATEWAY-HTTP,GATEWAY-GRPC,MESH-HTTP (TLSRoute is exercised through the declared TLSRoute, TLSRouteModeTerminate, and TLSRouteModeMixed features)
Test runnerIn-cluster Job (-test.timeout=30m), single attempt, backoffLimit: 0
Run date2026-04-26 (started 09:22 UTC)
ResultGo harness reports PASS · 0 failures · 125 top-level PASS · 471 sub-test PASS · 5 top-level SKIP (4 declared --skip-tests mesh opt-outs + 1 harness auto-skip for the undeclared UDPRoute alpha profile)
Wall-clock duration3 min 26 sec (206 s reported by the Go test harness; the -test.timeout=30m ceiling was never approached)
Container resourcesrequests: 100m CPU / 128Mi mem · limits: 500m CPU / 512Mi mem · per conformance pod

Dependency baseline