Gateway

Architecture

Cargo workspace, 11 crates, strictly layered — lower layers never depend on higher ones:

server → views → handler → {dag, engines} → {models, state} → {protocol, config} → consts
Crate Layer Role
consts L0 error codes, the Protocol enum
models L1 request/response domain types, typed params, usage, cost
protocol L1 OpenAI / Anthropic wire types, DSL response transforms
config L1 YAML config loading (conf/gateway.yaml)
state L2 auth, account pool, quotas, rate limits, ledger, batch/file stores (in-process defaults; Postgres/Redis fleet backends)
engines L3 engine implementations behind the Transport seam, SSE decoding, usage extraction, SigV4
dag L3 4-layer pipeline executor + nodes
handler L4 online/offline orchestration, DLP/blocklist plugins
task L5 background tasks (daily quota reset)
views L5 axum HTTP/WebSocket handlers, protocol conversion
server L6 binary entrypoint: config + state + transport wiring

Request flow

client ──► views (auth, parse, protocol normalize)
       ──► handler (pre plugins: blocklist, then DLP redact)
       ──► dag: preprocess        resolve model, quota check, cache lookup
              account_select      priority / PTU-first / cooldown-aware selection
              model_access        rate limits, engine call, retry-on-5xx failover
              post_process        usage → billing ledger, cache store
       ──► handler (post plugins) ──► views (JSON or SSE re-emit)

A client disconnect does not cancel the pipeline: every request runs on its own task (run_pipeline / spawn_stream_pipeline), so once admitted, quota and ledger accounting run to completion even if the caller goes away. Spawned background work (offline batches) likewise outlives the submitting request.

The DAG executes four fixed layers; nodes within a layer are topologically ordered by declared dependencies. account_select and model_access form a retry loop: an upstream 5xx excludes the failed account and reselects once; a PTU→paygo switch is recorded as ptu_spillover in the ledger.

Seams (traits)

Every boundary to the outside world is a trait with a deterministic default, so the whole pipeline is testable offline:

Testing