Documentation

Inference upstream

The model itself does not run inside the Eidola server. It runs in a separate confidential-compute deployment operated by an inference provider (currently Tinfoil), with its own attestation chain that the Eidola server verifies on every outbound connection.

This page explains what runs where, what the user is trusting at this layer, and how the trust is anchored.

Where the model runs

The upstream inference provider:

The Eidola server is a client of this enclave. It verifies the upstream’s attestation on every TCP+TLS connection it opens to the inference endpoint, using the same tinfoil-verifier crate the Eidola client uses to verify the Eidola server.

What the user is trusting at this layer

The user is trusting, in addition to the layers covered in client.md and server.md:

  1. That the model itself runs in confidential compute. This is verifiable: the inference upstream attests to a measurement that the Eidola server checks against the set of measurements it currently trusts (resolved at runtime — see below).
  2. That the model code’s published measurements match the published source. The inference provider publishes signed measurements via Sigstore against a specific source repository (e.g. tinfoilsh/confidential-model-router). The Eidola server verifies this provenance itself: it resolves the latest release’s measurement and verifies its Sigstore attestation end-to-end before trusting it.
  3. That the upstream provider’s confidential-compute deployment is genuine. This is the same trust as for the Eidola server’s own enclave — ultimately rooted in the hardware vendor (AMD, Intel, or NVIDIA) and its attestation chain.

What pins the upstream measurement

The set of allowed upstream enclave measurements is resolved at runtime, not baked into the binary. inference.tinfoil.sh is a router enclave that reverse-proxies to separate per-model GPU enclaves, and the router trusts those downstream enclaves via “the latest Sigstore-signed release of the repo” — so statically pinning the router’s measurement (and gating changes on a human PR) bought little rigor over the upstream provider’s own trust model while causing a fail-closed outage every time the provider shipped a router release. Instead, crates/eidola-server/src/upstream_trust matches the provider’s actual model: on boot and every ~10 minutes it resolves the provider’s latest release and verifies its Sigstore attestation end-to-end before trusting the measurement:

The allowed set is a rolling window of the two most recently resolved measurements (so an in-progress rolling deploy still attests). This holds from the very first boot: bootstrap resolves the latest release (the fatal readiness gate) and also folds in the immediately-previous published release (best-effort — a missing or unverifiable previous release just logs a warning and boots latest-only), so a cold start landing mid-deploy attests the still-draining old router enclave rather than aborting startup. A resolution or verification failure never clears or widens trust — the server keeps its current set, and if it can’t resolve a verified measurement at boot it refuses to start (there is no static fallback). This whole subsystem is transitional: when Eidola self-hosts inference it is replaced by a statically pinned measurement set.

What the user is not trusting

Per-connection verification

The Eidola server’s outbound HTTPS client (constructed by tinfoil-verifier::attesting_client) re-verifies the upstream enclave on every new TCP+TLS handshake. The mechanics are the same as for the client→server path, because they use the same crate:

A failed attestation rejects the request before any inference data crosses the wire.

Why a separate enclave at all

A reasonable question: why does the model run in a different enclave from the Eidola server? The full answer is partly structural and partly transitional.

Structurally, confidential-compute infrastructure for serving large language models requires specialized hardware (GPUs with NVIDIA confidential compute) and operational expertise that dedicated inference providers can supply most cleanly. Eidola’s role is the privacy and account layer around the inference, not the inference itself.

Transitionally, the upstream-provider model has the appealing property that the user’s trust chain at the inference layer ends at a measurement signed against the upstream’s source — which that source can be audited against independently of Eidola.

Two caveats apply to that second framing today:

The cost of the current split is one additional verification step (Eidola server → upstream) on each inference, which adds a small per-handshake latency cost on top of the connection-pooled normal request path.

The cvmimage / OVMF non-determinism caveat moved to gaps.md#build-chain-opacity, since it cuts across the whole server-side trust chain (not just inference upstream).

Edit this page on GitHub