These are promises ProxAI commits to. Breaking any of them is a breaking change that requires a major version bump and a migration note (see C30). They are more stable than field names or config defaults.
Strict config loading
config.toml with missing required fields always fails to start. ProxAI never boots into a partially-valid runtime state using implicit defaults.
Source owner
src/config.rs
Failure mode
Proxy starts with missing provider, route, protocol, or timeout data.
Suggested tests
- Config loading/default tests
- Startup validation tests
Local example generation
First run always generates config.example.toml in the app directory as a local reference.
Source owner
src/paths.rs and config bootstrap code
Failure mode
New users cannot discover the local configuration shape.
Suggested tests
- Generated app-directory defaults tests
Tracked example is canonical
The tracked config.example.toml in the repository is the canonical example. ProxAI never overwrites it at runtime.
Source owner
config.example.toml and config bootstrap code
Failure mode
Runtime generation mutates repository documentation source.
Suggested tests
- Config example generation tests
- Docs config coverage check
Tool-call timeout is required
[tool_calls].timeout_secs must be greater than zero, otherwise ProxAI fails to start.
Source owner
src/config.rs
Failure mode
Tool-call semantic stalls can hang indefinitely.
Suggested tests
- Config validation tests
- Streaming tool-call timeout tests
MCP stays local
The MCP listener always binds to a local address (127.0.0.1 by default) and is never exposed to external networks by ProxAI itself.
Source owner
Listener setup and config defaults
Failure mode
Control surface is exposed outside the local machine.
MCP is not a model path
MCP is a control surface only. Model requests flow through the Proxy listener, never through MCP.
Source owner
HTTP routing/listener setup
Failure mode
Model traffic reaches control endpoints.
Suggested tests
- Route/listener separation tests
Explicit routes win
Default providers are used only when no explicit route matches. A matching route always wins over defaults.
Failure mode
Default provider steals traffic from a matching route.
Suggested tests
- Route matching tests
- Proxy e2e route tests
Unsupported pairs fail explicitly
Unimplemented conversion pairs always fail explicitly. ProxAI never silently falls through to a default provider when a route matches but the protocol pair is unsupported.
Source owner
src/translation/ and routing dispatch
Failure mode
Unsupported conversion silently routes to a different provider.
Suggested tests
- Compatibility matrix coverage
- Unsupported pair e2e tests
Provider protocol is semantic
Provider protocol is the semantic identifier. Provider names are user labels and never change wire behavior.
Source owner
src/config.rs, src/provider/, src/translation/
Failure mode
Provider name accidentally changes serialization or response parsing.
Suggested tests
- Provider protocol dispatch tests
Request protocol guards are strict
If a route sets request_protocol and the model matches but the inbound protocol differs, ProxAI returns a configuration error instead of routing anyway.
Failure mode
Endpoint-specific routes silently fall through.
Suggested tests
- Protocol-aware route matching tests
OpenAI provider auth is controlled by ProxAI
Provider api_key is always sent upstream. For OpenAI providers (openai_responses, openai_chat_completions) it is sent as Authorization: Bearer <key> and any client-supplied Authorization header is ignored.
Source owner
src/provider/*/transport
Failure mode
Client credentials leak upstream or provider credentials are not used.
Suggested tests
- Provider transport header tests
Anthropic provider auth uses x-api-key
For Anthropic Messages providers, the key is sent as x-api-key.
Source owner
src/provider/*/transport
Failure mode
Anthropic-compatible upstream rejects auth or receives wrong auth header.
Suggested tests
- Anthropic transport header tests
Outbound protocol decides content type
Response Content-Type is decided by the outbound protocol, not passed through from the upstream.
Source owner
src/http_support/ and response translation
Failure mode
Client receives upstream content type incompatible with inbound protocol.
Suggested tests
- Response reconstruction tests
Headers are filtered
Upstream headers are filtered before forwarding. The forwardable set is explicitly controlled by ProxAI, never a verbatim copy of all upstream headers.
Source owner
src/http_support/
Failure mode
Private or protocol-incompatible upstream headers leak to the client.
Useful upstream diagnostic headers are preserved
For non-2xx upstream responses, ProxAI preserves useful diagnostic headers when the upstream actually provides them: Retry-After, upstream request id, rate-limit headers. It never fabricates these headers.
Source owner
src/error/ and upstream response handling
Failure mode
Clients lose actionable retry/rate-limit information or receive fabricated data.
Suggested tests
- Upstream error projection tests
Client errors carry status in payload
Client-facing errors always include a numeric status field inside the payload. This is essential for SSE error events where HTTP status can no longer be changed.
Source owner
src/error/render.rs
Failure mode
SSE error events lose status context.
Suggested tests
- HTTP and SSE error rendering tests
Internal error taxonomy is private
ProxAI never exposes its internal typed error taxonomy verbatim. Client-facing type values are a fixed stable enum, extended only additively.
Failure mode
Internal Rust error names become public API.
Suggested tests
- Error type projection tests
- Docs checker error type coverage
Upstream code and param are not fabricated
ProxAI never fabricates upstream code or param values. They are only present when the upstream actually provided them.
Failure mode
Clients make decisions from invented upstream metadata.
Suggested tests
- Upstream error body shape tests
Streams require terminal events
SSE streams are always observed for terminal events. A stream is considered complete only when the expected terminal event arrives (response.completed, [DONE], or message_stop).
Source owner
SSE scanner and streaming translation modules
Failure mode
Client treats semantically incomplete streams as successful.
Suggested tests
- Terminal event tests
- Incomplete stream tests
Tool-call stalls close predictably
Stalled tool-call argument streams always close within [tool_calls].timeout_secs. ProxAI never lets a client hang indefinitely after tool-call arguments have started.
Source owner
Streaming state machines and tool-call timeout handling
Failure mode
Client hangs forever after partial tool arguments.
SSE carrier is preserved
SSE bytes and text/event-stream content type are preserved through translation.
Source owner
src/http_support/, SSE translation modules
Failure mode
Streaming clients receive non-SSE carrier data.
Read timeout is idle-based
read_idle_timeout_secs is an idle-read timeout, not a total request duration cap. It only fires when no new upstream bytes arrive within the configured window.
Source owner
Provider transport/upstream read handling
Failure mode
Long but active streams are incorrectly cut off.
Private request data is not logged
ProxAI never logs request bodies, Authorization headers, API keys, or private prompts.
Source owner
src/observe/ and logging call sites
Failure mode
Private prompts or credentials appear in default logs.
Suggested tests
- Logging redaction review
- Request hint tests
Captures stay local
Capture artifacts are local files under the app directory only. They are never transmitted by ProxAI itself.
Source owner
src/observe/ capture writers
Failure mode
Capture artifacts leave the local machine automatically.
Capture paths are fixed
Capture paths are fixed and not configurable, to avoid accidental writes to arbitrary locations.
Source owner
src/observe/ and paths code
Failure mode
User-provided paths write private captures into unsafe locations.
Translation is carrier-pure
Translation stays pure at the HTTP carrier boundary. It accepts protocol values and payload/stream carriers, not HTTP Response/Body, route details, model rewrite details, or provider-private structs.
Source owner
src/translation/
Failure mode
Translation depends on HTTP/provider internals and becomes impossible to reason about pair-wise.
Suggested tests
- Boundary-focused conversion tests
No raw provider round-trips
ProxAI never round-trips raw provider structures across a translation pair. Each direction is independently translated into the target protocol's types.
Source owner
src/translation/
Failure mode
Target protocol receives provider-private structures.
Suggested tests
- Pair-specific response conversion tests
Provider quirks stay in provider code
Provider-local normalization belongs in provider/. General cross-protocol shape changes belong in translation/. Provider code must not hide protocol-to-protocol conversion.
Source owner
src/provider/ and src/translation/
Failure mode
Protocol conversion logic is hidden in provider-specific adapters.
Suggested tests
- Provider/request and translation boundary review
Client-facing error types are additive
Client-facing type values are extended additively. Existing values are never renamed or removed without a major version bump.
Source owner
src/error/render.rs and reference docs
Failure mode
Existing clients break on renamed or removed error types.
Suggested tests
- Error type coverage checker
Contract breaks are major-version changes
Breaking any contract in this page (C1–C30) is a breaking change that requires a major version bump and a migration note.
Source owner
Release process and docs
Failure mode
User-visible breaking behavior ships as a minor/patch change.