> ## Documentation Index
> Fetch the complete documentation index at: https://docs.redpill.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Channel Binding and Fail-Closed Forwarding

> Before forwarding a prompt to a confidential provider, the gateway binds the connection to the verified enclave and refuses to send if it cannot.

Verifying an upstream's attestation is not enough on its own. A verifier could prove a genuine
enclave exists while the gateway still talks to a different, unverified server. **Channel binding**
closes that gap: the value the gateway verifies is the same value it enforces on the wire before it
forwards your prompt.

## The two binding types

Every confidential provider produces exactly one binding, and that value lives inside the verified
attestation.

| Binding                  | What it is                                       | How the gateway enforces it                                                         |
| ------------------------ | ------------------------------------------------ | ----------------------------------------------------------------------------------- |
| `tls_spki_sha256`        | SHA-256 of the upstream's TLS public key (SPKI). | Pins the upstream HTTPS connection to that key before forwarding.                   |
| `e2ee_public_key_sha256` | SHA-256 of the upstream's end-to-end public key. | Encrypts the request body to that key, so only the attested enclave can decrypt it. |

Which providers use which binding is listed on the [Providers](/confidential-ai/providers) page.

## The invariant: verified implies an enforceable binding

The gateway treats verification and binding as one fact. A "verified" result that carries no
enforceable binding is rejected. A provider can never be "verified but unpinned". This is enforced in
the gateway, not left to configuration.

## Fail-closed forwarding

For a confidential model, `upstream.verified.required` is `true`. If the gateway cannot verify the
upstream, or cannot enforce the verified binding on the actual connection, it does not send your
prompt. Retries and reconnects cannot bypass this: if the channel binding no longer matches, the
gateway re-verifies before forwarding.

```mermaid theme={null}
flowchart TD
  A["Confidential request"] --> B{"Upstream verified<br/>and binding enforceable?"}
  B -->|"Yes"| C["Forward prompt over bound channel"]
  B -->|"No"| D["Reject. Prompt is not sent."]
```

For a routed model, `required` is `false`. The gateway forwards to the third-party provider over
ordinary TLS without an attested binding, and the receipt records `result: failed`. Your prompt still
leaves the gateway, so use [confidential models](/confidential-ai/confidential-models) when the
upstream must be attested. See [Trust boundary](/confidential-ai/trust-boundary) for the full picture.

## How you confirm it

You do not enforce the binding yourself; the gateway does, before forwarding. What you verify after
the fact is that it happened:

1. Verify the [attestation report](/confidential-ai/attestation-report) and the
   [receipt](/confidential-ai/receipts).
2. Read `upstream.verified`. For a confidential response, `result` is `verified` and `required` is
   `true`, and the event references the [attested session](/confidential-ai/attested-sessions) whose
   binding the gateway enforced.

## Next

<CardGroup cols={2}>
  <Card title="Providers" icon="server" href="/confidential-ai/providers">
    Binding type and attested claims per provider.
  </Card>

  <Card title="Trust boundary" icon="shield-halved" href="/confidential-ai/trust-boundary">
    What the gateway does and does not protect.
  </Card>
</CardGroup>
