Request routing
How requests are normalized and forwarded to provider adapters.
The proxy exposes an OpenAI-compatible chat completion endpoint and diagnostic auth probes. Every chat request is parsed, validated, and authenticated end-to-end, then routed to the mock or live provider (ADR-0012, ADR-0013).
Protected routes
/v1/chat/completionsOpenAI-compatible chat completions. Requires ProxyChatCompletion permission. Mock mode returns 200; unknown models return 501.
/v1/internal/auth-probeDiagnostic route returning org_id and permissions from the bearer token.
/v1/orgs/{org_id}/auth-probeDiagnostic route with explicit path org; must match token org.
Middleware chain for chat
Global middleware (metrics, request ID, logging) wraps all routes. Chat-specific middleware runs in the order above — auth never executes on oversize or wrong Content-Type bodies. chatParse attaches the validated body; providerRouter attaches the selected provider.Provider (or returns 501 PROVIDER_NOT_CONFIGURED).
Normalization pipeline
Body size gate
Payloads over IBEX_MAX_REQUEST_BODY_BYTES (default 1 MiB) return 413 before JSON parse.
Content-Type gate
POST bodies must be application/json; otherwise 415.
JSON parse
Malformed JSON returns 400 INVALID_JSON with request_id in the envelope.
Semantic validation
Required fields (model, messages) produce field_errors array per ADR-0013.
Provider handoff
ProviderRoutingMiddleware resolves model → adapter; unknown models return 501 PROVIDER_NOT_CONFIGURED. Handler forwards via context provider.
Minimal valid body
{
"model": "gpt-4o",
"messages": [
{ "role": "user", "content": "Hello" }
]
}Validation error example
HTTP 400 with structured field errors:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"request_id": "0192a3b4-c5d6-7890-abcd-ef1234567890",
"timestamp": "2026-06-14T12:00:00Z",
"field_errors": [
{
"field": "model",
"code": "REQUIRED",
"message": "model is required"
}
]
}
}Optional docs_url appears when IBEX_ERROR_DOCS_BASE is configured — links to API errors.
Send a routed request
curl -s -w "\nHTTP %{http_code}\n" \
-X POST http://localhost:8080/v1/chat/completions \
-H "Authorization: Bearer ${IBEX_DEV_TOKEN}" \
-H "X-IBEX-Agent-ID: ${IBEX_DEV_AGENT_ID}" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"ping"}]}'Default mock mode expected: HTTP 200 for registered models. 501 PROVIDER_NOT_CONFIGURED means the model is not in the registry.
Path org enforcement
On /v1/orgs/{org_id}/auth-probe, the path parameter must be a valid UUID and must equal the organization embedded in the validated token. Cross-tenant attempts return 403 — never 404 — per Security authentication.
| Scenario | HTTP | Code |
|---|---|---|
| Invalid UUID in path | 400 | INVALID_PATH_ORG |
| Token org A, path org B | 403 | PATH_ORG_MISMATCH |
| Matching org | 200 | — |
Request correlation
Every response includes:
X-Request-ID— propagated to auth gRPC asx-request-idmetadataX-Trace-ID— OpenTelemetry traceX-Response-Time— handler duration
Use request_id from JSON errors to grep proxy and auth logs during integration debugging. See Request lifecycle.
Phase 2 forwarding
When a provider adapter registers, the handler will:
- Select adapter by model prefix or org configuration
- Attach org/agent metadata for audit and tracing
- Stream OpenAI-compatible SSE or JSON back to the client
See Provider adapters for mock vs live configuration and roadmap for remaining exit-gate work.
Related
- Authentication — credentials required before routing
- Provider adapters — Phase 2 upstream contract
- Overview — full endpoint table
- Chat completions — request shape and headers
Was this page helpful?
Last updated on