Skip to main content
IronLabs commits to specific negative guarantees: things that never cross tenant or product boundaries. This page lists them, the boundary they apply to, and the underlying mechanism — so you can verify the guarantee, not just trust it.

Isolation guarantees

BoundaryGuaranteeMechanism
Tenant dataAPI keys, trained Custom Routers, training datasets, and usage logs are never shared across userId.Every row in PostgreSQL carries a userId foreign key. Clerk auth validates the user on every dashboard request; validate_token validates the API key on every router call. There is no shared-mutable cache between tenants.
Model trafficA request dispatched to provider X is never logged into provider Y.Per-call provider routing. No cross-provider retry happens unless you explicitly populate fallback_models.
Custom RoutersTrained routers are never callable across usersmodel_id is scoped to the training userId.CustomRouter.userId is enforced in db_utils.can_user_create_router and get_router_model. Calling another user’s model_id returns 404, not 403 — we don’t acknowledge cross-tenant existence.
AgentOpt sandboxesEach optimization iteration runs in an isolated Modal Sandbox. No filesystem state, no network state, and no in-memory state survives across iterations.Modal Sandbox provides container-level isolation; the sandbox is destroyed and recreated per iteration. Code, dataset, and dependencies are re-mounted from your uploaded ZIP each time.
Provider keys (per-provider mode)When you supply your own providers config in the Node SDK, those keys are never sent to the IronLabs routing API.Resolution happens client-side in the SDK before the request leaves your process. The routing API receives a pre-resolved gateway URL and your IronLabs key only.
Prompt-Opt OpenRouter keysOptimizer-model calls (GEPA / MIPROv2) hit OpenRouter directly using your OpenRouter key. IronLabs neither stores it long-term nor uses it for any other purpose.The key is held in memory for the duration of the optimization job and discarded when the job finalizes. Audit trail in Langfuse.

What this means in practice

  • Cross-tenant data leak through routing. Not possible — the router’s input is a single tenant’s message; the classifier output is consumed inline and discarded; the only persisted artifact is ModelSelectUsage, which is userId-scoped.
  • A neighboring user’s bad-faith Custom Router affecting your routing. Not possible — your requests route through the pre-trained router unless you set routerId to one you own.
  • A leaked AgentOpt iteration leaving state behind. Not possible — sandboxes are torn down per iteration. The only artifact that survives is the iteration’s checkpoint row in AgentOptRuns (your userId).
  • Provider key exfiltration via a logged request. Not possible in per-provider mode — keys never traverse our backend. In gateway mode (OpenRouter, LLM Gateway), the key is stored in your account’s encrypted secrets and only injected at egress.

Architecture, in one sentence

All requests terminate at the FastAPI gateway on Modal; per-tenant state lives in userId-scoped rows in PostgreSQL; there is no peer-to-peer state between tenants, between routers, or between optimization runs.

What we do not guarantee

Honesty matters. These are not currently guaranteed:
  • At-rest encryption of training datasets. Datasets you upload to a public URL for Custom Router training are downloaded into Modal Volumes and persisted in the trained model. If the dataset itself is sensitive, redact it before uploading.
  • Cross-region failover. A single region outage will produce errors until that region recovers.
  • Provider-level isolation. When a request is forwarded to OpenAI or Anthropic, that provider’s security model applies; we cannot guarantee what they log on their side.

Routing Lifecycle

See where in the lifecycle each isolation boundary is enforced.

API Authentication

Bearer-token scheme and key rotation.

AgentOpt

How the per-iteration sandbox is mounted.

Custom Router

Where your training data lives after training.