IBEX Harness
DocsBenchmarksBlogChangelogRoadmap
GitHub
IBEX Harness

Documentation

Architecture Decision RecordsADR-0002: Repository foundation bootstrapADR-0003: Branch protection and merge policyADR-0004: Protobuf and code generation policyADR-0005: Postgres migration strategyADR-0006: Auth protobuf contract (`ibex.auth.v1`)ADR-0007: Auth token validation implementationADR-0008: Security scanning and CI quality gatesADR-0009: Permission bitmap layoutADR-0010: Cryptography policyADR-0011: Proxy auth gRPC client and middlewareADR-0012: Proxy request normalization (OpenAI chat)ADR-0013: Proxy input validation and stable error envelopeADR-0014: Core domain migration sequencingADR-0015: Proxy rate limit skeleton (Phase 1)ADR-0016: Proxy agent identity verification (Phase 1)ADR-0017: Request ID and trace context strategy (Phase 1)ADR-0018: Graceful shutdown contract (Phase 1)ADR-0019: OpenTelemetry provider configuration (Phase 1)ADR-0020: Shared package boundaries — `packages/config` and `packages/apierror`ADR-0021: Prometheus Metric Catalog (Phase 1)ADR-0022: Health check contract (Phase 1)ADR-0023: Docs site architecture (Phase 1.5)ADR-0024: Benchmark data publishing modelADR-0025: LLM provider abstractionADR-0026: OpenAI client designADR-0027: Streaming dual-write strategyADR-0028: Auth cache designADR-0029: Token revocation propagation via Redis pub/subADR-0030: Directive versioning strategyADR-0031: System prompt injection strategyADR-0032: Session data model and retentionADR-0033: ClickHouse llm_traces schema and retentionADR-0034: Proxy overhead performance measurement methodologyADR-0035: Chat Idempotency-Key Redis dedupeADR-0038: Context assembly service design and gRPC contractADR-0039: Proxy Postgres ownership for session and directive storesADR-0040: Anthropic provider adapterADR-0041: Model capability registryADR-0042: Self-hosted OpenAI-compatible LLM adapterADR-0043: Tokenizer registry architectureADR-0044: Non-streaming response pipelineADR-0045: Streaming response transformationADR-0046: Embedder interface and profile registryADR-0047: Memory temporal validity foundationADR-0048: Memory multi-label categoriesADR-0049: Memory relationship graph readinessADR-0050: MCP server skeleton (transport, auth, audit)ADR-0051: Local LGTM observability stack (Phase 2.5 exit pull-forward)ADR-0052: Memory schema v2 expand (HNSW, quality columns)ADR-0053: Vector store abstraction and composite scoring v2ADR-0054: In-process Presidio PII detection in memoryADR-0055: Memory write-path exact and near-duplicate dedupADR-0056: Temporal-interval-aware conflict detectionADR-0057: Memory write-path persistence and orchestrationADR-0058: Semantic search FTS fallback triggerADR-0059: Hot cache read pathADR-0060: Memory service tenant isolation architectureADR-0061: Retrieval-quality benchmark methodologyADR-0062: Worker task observability and dead-letter handlingADR-0063: Extraction output schema v2ADR-0064: Extraction provider registry and batch executionADR-0065: Extraction batch idempotency and turn pointer orderingADR-0066: Extraction quality evaluation harnessADR-0067: Context capability catalog generate-and-diff for token budgetsADR-0068: Composite scoring-time relevance gateADR-0069: Context packer bounded DP knapsackADR-0070: Context formatting locked ordering and session nonceADR-0071: Context assembly gRPC degradation ladder and retrieval deadlineADR-0072: Extraction enqueue via worker HTTP (not Celery Redis wire format)ADR-0073: Organization Lifecycle and Cascading SuspensionADR-0074 Provider Credential StorageADR-0075 Per-Org Model Routing PolicyADR-0076: Circuit Breaker per ProviderADR-0077: Provider Fallback RoutingADR-0078: Operator runtime topology & environment contract (4.P.0)ADR-0079: Operator session RS256 dual-verify and TOTP step-upIBEX Console service rename and boundaryADR-0081: Fail-closed Proxy runtime controlsD2 metadata-only trace read contractD2 publication, identity, query, and lifecycle contract
ADRs›ADR-0081: Fail-closed Proxy runtime controls
ADRs

ADR-0081: Fail-closed Proxy runtime controls

Redis-backed rate-limit and organization model-policy dependency failure behavior.

ADR-0081: Fail-closed Proxy runtime controls

  • Status: Accepted
  • Date: 2026-09-24
  • Authors: IBEX Harness team
  • Amends: ADR-0015 and ADR-0075

Context

The Proxy controls paid-provider access, organization model eligibility, and shared request budgets. Two existing fallbacks could silently weaken those controls: rate-limit middleware proceeded when Redis operations failed, and an environment-variable escape hatch selected a provider registry without organization policies when PostgreSQL was absent. A missing Redis URL also constructed an always-allow limiter without regard to environment. Availability and accurate error classification still matter: infrastructure failure is not equivalent to a request quota denial or an organization policy denial.

Decision

  1. Runtime profile and shared limiter must be explicit. Proxy IBEX_ENV must be explicitly set to development, staging, or production; neither environment parsing nor Config.ApplyDefaults() may manufacture a development profile. Direct config validation rejects a missing profile. Outside development, missing REDIS_URL is invalid and fails startup/config validation. A configured Redis URL whose shared rate-limit operation fails produces a 503 SERVICE_DEGRADED; the request must not reach provider work. This is neither a 429 RATE_LIMITED response nor permission to proceed without a limit.
  2. Model selection never bypasses organization policy. Remove PassthroughRegistry and IBEX_MODEL_POLICY_ALLOW_PASSTHROUGH as operational controls. Unset or false legacy values do not enable bypass; true fails startup with a migration diagnostic. When the model-policy store or required routing dependencies are unavailable, deny provider selection with 503 SERVICE_DEGRADED. A valid policy denial remains 403 MODEL_NOT_ALLOWED; an unknown model after an allow decision remains 501 PROVIDER_NOT_CONFIGURED.
  3. Development/test exceptions are explicit. A local development environment may omit Redis and use the Noop limiter for local work. Tests may provide isolated fake implementations through test-only adapters. Production runtime types contain no allow-without-policy model resolver.
  4. Availability trade-off is intentional. During Redis or PostgreSQL policy-store failure, paid chat can become unavailable rather than bypassing the configured tenant policy or shared limit. Restore the dependency, roll back to an evidence-backed compatible deployment, or disable the affected capability; do not weaken the controls temporarily.
  5. Errors are observable without leaking secrets. Continue rate-limit Redis error metrics and model-policy enabled-state metrics. Log dependency failure class and organization/request correlation where permitted, but do not log credentials, DSNs, or raw provider data. Redis remains a critical /ready dependency in every profile. Development may start and use the Noop request limiter without Redis, but /ready intentionally remains degraded until Redis is available; local probes and runbooks must account for this distinction.

Consequences

  • Operators must explicitly set the Proxy profile and provide an actual shared Redis URL, then verify Redis health before deploying in staging or production. In development, missing Redis does not block process startup or request handling through the Noop limiter, but it does keep /ready degraded. Helm values do not by themselves prove profile/secret delivery or provision a live endpoint; see 4.P.0 and 4.P.5.
  • Provider routing and rate-limit tests must distinguish dependency-unavailable 503 from policy-denied 403, exhausted-quota 429, and unconfigured-provider 501, and prove the next handler/provider was not invoked on dependency failure.
  • The old accepted Phase 1 fail-open choice in ADR-0015 is historical and superseded for current multi-provider runtime by this ADR. POSTGRES_DSN absence must not turn off policy enforcement silently.
  • This ADR does not settle emergency local rate limiting, Redis HA/failover design, AuthService's separate internal ValidateToken limiter, or chat idempotency-store behavior. Those remain separate contracts and risks, not implicit exceptions to this decision.

Verification

The implementation must have tests for missing non-development Redis configuration, development Noop behavior, Redis operation failure and no provider invocation, model-policy missing-store startup/runtime behavior, and distinct HTTP status/error envelopes for policy denial versus dependency unavailability. Passing those tests proves source behavior only; deployed readiness, external Redis secrets, and production/staging rollout evidence are owned by P0/P5/E2.

Related

  • ADR-0015 — Proxy rate-limit skeleton
  • ADR-0075 — Per-org model routing policy
  • Proxy rate limiting
  • Phase 4 findings

Was this page helpful?

Edit on GitHub

Last updated on

PreviousIBEX Console service rename and boundaryNextD2 metadata-only trace read contract

On this page

  • Context
  • Decision
  • Consequences
  • Verification
  • Related
0%