What "blind relay" means concretely (verified from source)
For a tinfoil-* request, the end-to-end flow (from
routstr-core/docs/ehbp-proxy-support.md and routstr-sdk/client/TinfoilSecure.ts):
1. Pi sends a normal OpenAI JSON request to routstrd :8008/v1 with
model: "tinfoil-kimi-k3".
2. @routstr/sdk's RoutstrClient sees the tinfoil- prefix → calls
prepareTinfoilClient() → new SecureClient({ baseURL: <provider>, transport: "ehbp" })
→ client.ready() fetches + verifies the Tinfoil attestation bundle (enclave code
fingerprint, HPKE public key).
3. The SDK HPKE-encrypts the JSON body, sets Ehbp-Encapsulated-Key, sets
X-Routstr-Model: tinfoil-kimi-k3, strips the tinfoil- prefix from the model id
inside the encrypted body (enclave sees kimi-k3).
4. routstrd routes the encrypted request to the best provider (often your own
routstr-core). The provider detects Ehbp-Encapsulated-Key, does not parse the
body, forwards the raw ciphertext to Tinfoil's enclave, and adds
X-Tinfoil-Request-Usage-Metrics: true.
5. The attested enclave decrypts inside the TEE, runs inference, returns an
EHBP-encrypted response with Ehbp-Response-Nonce and X-Tinfoil-Usage-Metrics.
6. The provider passes the encrypted response through untouched. The SDK decrypts it
locally using the nonce and hands plaintext back to Pi.
7. Billing: the provider reads X-Tinfoil-Usage-Metrics (header for non-streaming,
HTTP trailer for streaming) and charges actual token cost — without ever decrypting.
Net: Routstr (both routstrd and the provider) sees only ciphertext + metadata headers.
The only entity that sees plaintext is the attested Tinfoil enclave. This is the same
trust model as running Tinfoil's SecureClient directly, with Routstr acting as a
Nostr-discovered, Cashu-paying blind relay in between.
For a tinfoil-* request, the end-to-end flow (from
routstr-core/docs/ehbp-proxy-support.md and routstr-sdk/client/TinfoilSecure.ts):
1. Pi sends a normal OpenAI JSON request to routstrd :8008/v1 with
model: "tinfoil-kimi-k3".
2. @routstr/sdk's RoutstrClient sees the tinfoil- prefix → calls
prepareTinfoilClient() → new SecureClient({ baseURL: <provider>, transport: "ehbp" })
→ client.ready() fetches + verifies the Tinfoil attestation bundle (enclave code
fingerprint, HPKE public key).
3. The SDK HPKE-encrypts the JSON body, sets Ehbp-Encapsulated-Key, sets
X-Routstr-Model: tinfoil-kimi-k3, strips the tinfoil- prefix from the model id
inside the encrypted body (enclave sees kimi-k3).
4. routstrd routes the encrypted request to the best provider (often your own
routstr-core). The provider detects Ehbp-Encapsulated-Key, does not parse the
body, forwards the raw ciphertext to Tinfoil's enclave, and adds
X-Tinfoil-Request-Usage-Metrics: true.
5. The attested enclave decrypts inside the TEE, runs inference, returns an
EHBP-encrypted response with Ehbp-Response-Nonce and X-Tinfoil-Usage-Metrics.
6. The provider passes the encrypted response through untouched. The SDK decrypts it
locally using the nonce and hands plaintext back to Pi.
7. Billing: the provider reads X-Tinfoil-Usage-Metrics (header for non-streaming,
HTTP trailer for streaming) and charges actual token cost — without ever decrypting.
Net: Routstr (both routstrd and the provider) sees only ciphertext + metadata headers.
The only entity that sees plaintext is the attested Tinfoil enclave. This is the same
trust model as running Tinfoil's SecureClient directly, with Routstr acting as a
Nostr-discovered, Cashu-paying blind relay in between.