Request routing
How requests are normalized and forwarded to provider adapters.
The proxy exposes an OpenAI-compatible chat completion endpoint and diagnostic auth probes. In Phase 1 every chat request is parsed, validated, and authenticated end-to-end; provider forwarding stops with 501 PROVIDER_NOT_CONFIGURED until Phase 2 registers an adapter (ADR-0012, ADR-0013).
Protected routes
/v1/chat/completionsOpenAI-compatible chat completions. Requires ProxyChatCompletion permission. Phase 1 returns 501 after validation.
/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.
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
Phase 1 stub returns 501 PROVIDER_NOT_CONFIGURED.
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"}]}'Phase 1 expected: HTTP 501, error.code = PROVIDER_NOT_CONFIGURED. That confirms routing, auth, agent verify, rate limit, and validation all succeeded.
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
Until then, treat 501 as the healthy Phase 1 outcome. Track progress: Provider adapters and roadmap.
Related
- Authentication — credentials required before routing
- Provider adapters — Phase 2 upstream contract
- Overview — full endpoint table
- Chat completions — Phase 1 HTTP stub
Was this page helpful?
Last updated on